mirror of
https://github.com/geode-sdk/geode.git
synced 2024-11-22 23:48:08 -05:00
macos map add things
This commit is contained in:
parent
7836e60b86
commit
db02c3dd1a
4 changed files with 531 additions and 260 deletions
347
loader/include/Geode/c++stl/gnustl-map.hpp
Normal file
347
loader/include/Geode/c++stl/gnustl-map.hpp
Normal file
|
@ -0,0 +1,347 @@
|
|||
#pragma once
|
||||
|
||||
namespace geode::stl {
|
||||
struct _rb_tree_base {
|
||||
bool m_isblack;
|
||||
_rb_tree_base* m_parent;
|
||||
_rb_tree_base* m_left;
|
||||
_rb_tree_base* m_right;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct _rb_tree_node : public _rb_tree_base {
|
||||
T m_value;
|
||||
};
|
||||
|
||||
inline void _rb_tree_rotate_left(_rb_tree_base* const x, _rb_tree_base*& root);
|
||||
inline void _rb_tree_rotate_right(_rb_tree_base* const x, _rb_tree_base*& root);
|
||||
inline void _rb_insert_rebalance(
|
||||
bool const insert_left, _rb_tree_base* x, _rb_tree_base* p, _rb_tree_base& header
|
||||
);
|
||||
inline _rb_tree_base* _rb_increment(_rb_tree_base* __x) noexcept;
|
||||
inline _rb_tree_base* _rb_decrement(_rb_tree_base* __x) noexcept;
|
||||
inline _rb_tree_base* _rb_rebalance_for_erase(_rb_tree_base* const __z, _rb_tree_base& __header) noexcept;
|
||||
|
||||
template <typename T>
|
||||
struct _rb_tree_iterator {
|
||||
typedef T value_type;
|
||||
typedef T& reference;
|
||||
typedef T* pointer;
|
||||
|
||||
typedef _rb_tree_iterator<T> _Self;
|
||||
typedef _rb_tree_base* _Base_ptr;
|
||||
typedef _rb_tree_node<T>* _Link_type;
|
||||
|
||||
_rb_tree_iterator() : m_node() {}
|
||||
|
||||
explicit _rb_tree_iterator(_Base_ptr __x) noexcept : m_node(__x) {}
|
||||
|
||||
reference operator*() const noexcept {
|
||||
return *static_cast<_Link_type>(m_node)->m_value;
|
||||
}
|
||||
|
||||
pointer operator->() const noexcept {
|
||||
return static_cast<_Link_type>(m_node)->m_value;
|
||||
}
|
||||
|
||||
_Self& operator++() noexcept {
|
||||
m_node = _rb_increment(m_node);
|
||||
return *this;
|
||||
}
|
||||
|
||||
_Self operator++(int) noexcept {
|
||||
_Self __tmp = *this;
|
||||
m_node = _rb_increment(m_node);
|
||||
return __tmp;
|
||||
}
|
||||
|
||||
_Self& operator--() noexcept {
|
||||
m_node = _rb_decrement(m_node);
|
||||
return *this;
|
||||
}
|
||||
|
||||
_Self operator--(int) noexcept {
|
||||
_Self __tmp = *this;
|
||||
m_node = _rb_decrement(m_node);
|
||||
return __tmp;
|
||||
}
|
||||
|
||||
bool operator==(_Self const& __x) const noexcept {
|
||||
return m_node == __x.m_node;
|
||||
}
|
||||
|
||||
bool operator!=(_Self const& __x) const noexcept {
|
||||
return m_node != __x.m_node;
|
||||
}
|
||||
|
||||
_Base_ptr m_node;
|
||||
};
|
||||
|
||||
inline void _rb_tree_rotate_left(_rb_tree_base* const x, _rb_tree_base*& root) {
|
||||
_rb_tree_base* const y = x->m_right;
|
||||
|
||||
x->m_right = y->m_left;
|
||||
if (y->m_left != 0) y->m_left->m_parent = x;
|
||||
y->m_parent = x->m_parent;
|
||||
|
||||
if (x == root) root = y;
|
||||
else if (x == x->m_parent->m_left) x->m_parent->m_left = y;
|
||||
else x->m_parent->m_right = y;
|
||||
y->m_left = x;
|
||||
x->m_parent = y;
|
||||
}
|
||||
|
||||
inline void _rb_tree_rotate_right(_rb_tree_base* const x, _rb_tree_base*& root) {
|
||||
_rb_tree_base* const y = x->m_left;
|
||||
|
||||
x->m_left = y->m_right;
|
||||
if (y->m_right != 0) y->m_right->m_parent = x;
|
||||
y->m_parent = x->m_parent;
|
||||
|
||||
if (x == root) root = y;
|
||||
else if (x == x->m_parent->m_right) x->m_parent->m_right = y;
|
||||
else x->m_parent->m_left = y;
|
||||
y->m_right = x;
|
||||
x->m_parent = y;
|
||||
}
|
||||
|
||||
inline void _rb_insert_rebalance(
|
||||
bool const insert_left, _rb_tree_base* x, _rb_tree_base* p, _rb_tree_base& header
|
||||
) {
|
||||
_rb_tree_base*& root = header.m_parent;
|
||||
|
||||
x->m_parent = p;
|
||||
x->m_left = 0;
|
||||
x->m_right = 0;
|
||||
x->m_isblack = false;
|
||||
|
||||
if (insert_left) {
|
||||
p->m_left = x;
|
||||
|
||||
if (p == &header) {
|
||||
header.m_parent = x;
|
||||
header.m_right = x;
|
||||
}
|
||||
else if (p == header.m_left) {
|
||||
header.m_left = x;
|
||||
}
|
||||
}
|
||||
else {
|
||||
p->m_right = x;
|
||||
|
||||
if (p == header.m_right) {
|
||||
header.m_right = x;
|
||||
}
|
||||
}
|
||||
|
||||
while (x != root && x->m_parent->m_isblack == false) {
|
||||
_rb_tree_base* const xpp = x->m_parent->m_parent;
|
||||
|
||||
if (x->m_parent == xpp->m_left) {
|
||||
_rb_tree_base* const y = xpp->m_right;
|
||||
if (y && y->m_isblack == false) {
|
||||
x->m_parent->m_isblack = true;
|
||||
y->m_isblack = true;
|
||||
xpp->m_isblack = false;
|
||||
x = xpp;
|
||||
}
|
||||
else {
|
||||
if (x == x->m_parent->m_right) {
|
||||
x = x->m_parent;
|
||||
_rb_tree_rotate_left(x, root);
|
||||
}
|
||||
x->m_parent->m_isblack = true;
|
||||
xpp->m_isblack = false;
|
||||
_rb_tree_rotate_right(xpp, root);
|
||||
}
|
||||
}
|
||||
else {
|
||||
_rb_tree_base* const y = xpp->m_left;
|
||||
if (y && y->m_isblack == false) {
|
||||
x->m_parent->m_isblack = true;
|
||||
y->m_isblack = true;
|
||||
xpp->m_isblack = false;
|
||||
x = xpp;
|
||||
}
|
||||
else {
|
||||
if (x == x->m_parent->m_left) {
|
||||
x = x->m_parent;
|
||||
_rb_tree_rotate_right(x, root);
|
||||
}
|
||||
x->m_parent->m_isblack = true;
|
||||
xpp->m_isblack = false;
|
||||
_rb_tree_rotate_left(xpp, root);
|
||||
}
|
||||
}
|
||||
}
|
||||
root->m_isblack = true;
|
||||
}
|
||||
|
||||
inline _rb_tree_base* _rb_increment(_rb_tree_base* __x) noexcept {
|
||||
if (__x->m_right != 0) {
|
||||
__x = __x->m_right;
|
||||
while (__x->m_left != 0)
|
||||
__x = __x->m_left;
|
||||
}
|
||||
else {
|
||||
_rb_tree_base* __y = __x->m_parent;
|
||||
while (__x == __y->m_right) {
|
||||
__x = __y;
|
||||
__y = __y->m_parent;
|
||||
}
|
||||
if (__x->m_right != __y) __x = __y;
|
||||
}
|
||||
return __x;
|
||||
}
|
||||
|
||||
inline _rb_tree_base* _rb_decrement(_rb_tree_base* __x) noexcept {
|
||||
if (!__x->m_isblack && __x->m_parent->m_parent == __x) __x = __x->m_right;
|
||||
else if (__x->m_left != 0) {
|
||||
_rb_tree_base* __y = __x->m_left;
|
||||
while (__y->m_right != 0)
|
||||
__y = __y->m_right;
|
||||
__x = __y;
|
||||
}
|
||||
else {
|
||||
_rb_tree_base* __y = __x->m_parent;
|
||||
while (__x == __y->m_left) {
|
||||
__x = __y;
|
||||
__y = __y->m_parent;
|
||||
}
|
||||
__x = __y;
|
||||
}
|
||||
return __x;
|
||||
}
|
||||
|
||||
inline _rb_tree_base* _rb_rebalance_for_erase(
|
||||
_rb_tree_base* const __z, _rb_tree_base& __header
|
||||
) noexcept {
|
||||
_rb_tree_base*& __root = __header.m_parent;
|
||||
_rb_tree_base*& __leftmost = __header.m_left;
|
||||
_rb_tree_base*& __rightmost = __header.m_right;
|
||||
_rb_tree_base* __y = __z;
|
||||
_rb_tree_base* __x = 0;
|
||||
_rb_tree_base* __x_parent = 0;
|
||||
|
||||
if (__y->m_left == 0) // __z has at most one non-null child. y == z.
|
||||
__x = __y->m_right; // __x might be null.
|
||||
else if (__y->m_right == 0) // __z has exactly one non-null child. y == z.
|
||||
__x = __y->m_left; // __x is not null.
|
||||
else {
|
||||
// __z has two non-null children. Set __y to
|
||||
__y = __y->m_right; // __z's successor. __x might be null.
|
||||
while (__y->m_left != 0)
|
||||
__y = __y->m_left;
|
||||
__x = __y->m_right;
|
||||
}
|
||||
if (__y != __z) {
|
||||
// relink y in place of z. y is z's successor
|
||||
__z->m_left->m_parent = __y;
|
||||
__y->m_left = __z->m_left;
|
||||
if (__y != __z->m_right) {
|
||||
__x_parent = __y->m_parent;
|
||||
if (__x) __x->m_parent = __y->m_parent;
|
||||
__y->m_parent->m_left = __x; // __y must be a child of m_left
|
||||
__y->m_right = __z->m_right;
|
||||
__z->m_right->m_parent = __y;
|
||||
}
|
||||
else __x_parent = __y;
|
||||
if (__root == __z) __root = __y;
|
||||
else if (__z->m_parent->m_left == __z) __z->m_parent->m_left = __y;
|
||||
else __z->m_parent->m_right = __y;
|
||||
__y->m_parent = __z->m_parent;
|
||||
std::swap(__y->m_isblack, __z->m_isblack);
|
||||
__y = __z;
|
||||
// __y now points to node to be actually deleted
|
||||
}
|
||||
else { // __y == __z
|
||||
__x_parent = __y->m_parent;
|
||||
if (__x) __x->m_parent = __y->m_parent;
|
||||
if (__root == __z) __root = __x;
|
||||
else if (__z->m_parent->m_left == __z) __z->m_parent->m_left = __x;
|
||||
else __z->m_parent->m_right = __x;
|
||||
if (__leftmost == __z) {
|
||||
if (__z->m_right == 0) // __z->m_left must be null also
|
||||
__leftmost = __z->m_parent;
|
||||
// makes __leftmost == _M_header if __z == __root
|
||||
else {
|
||||
__leftmost = __x;
|
||||
while (__leftmost->m_left != 0)
|
||||
__leftmost = __leftmost->m_left;
|
||||
}
|
||||
}
|
||||
if (__rightmost == __z) {
|
||||
if (__z->m_left == 0) // __z->m_right must be null also
|
||||
__rightmost = __z->m_parent;
|
||||
// makes __rightmost == _M_header if __z == __root
|
||||
else { // __x == __z->m_left
|
||||
__rightmost = __x;
|
||||
while (__rightmost->m_right != 0)
|
||||
__rightmost = __rightmost->m_right;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (__y->m_isblack != false) {
|
||||
while (__x != __root && (__x == 0 || __x->m_isblack))
|
||||
if (__x == __x_parent->m_left) {
|
||||
_rb_tree_base* __w = __x_parent->m_right;
|
||||
if (__w->m_isblack == false) {
|
||||
__w->m_isblack = true;
|
||||
__x_parent->m_isblack = false;
|
||||
_rb_tree_rotate_left(__x_parent, __root);
|
||||
__w = __x_parent->m_right;
|
||||
}
|
||||
if ((__w->m_left == 0 || __w->m_left->m_isblack == true) &&
|
||||
(__w->m_right == 0 || __w->m_right->m_isblack == true)) {
|
||||
__w->m_isblack = false;
|
||||
__x = __x_parent;
|
||||
__x_parent = __x_parent->m_parent;
|
||||
}
|
||||
else {
|
||||
if (__w->m_right == 0 || __w->m_right->m_isblack == true) {
|
||||
__w->m_left->m_isblack = true;
|
||||
__w->m_isblack = false;
|
||||
_rb_tree_rotate_right(__w, __root);
|
||||
__w = __x_parent->m_right;
|
||||
}
|
||||
__w->m_isblack = __x_parent->m_isblack;
|
||||
__x_parent->m_isblack = true;
|
||||
if (__w->m_right) __w->m_right->m_isblack = true;
|
||||
_rb_tree_rotate_left(__x_parent, __root);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// same as above, with m_right <-> m_left.
|
||||
_rb_tree_base* __w = __x_parent->m_left;
|
||||
if (__w->m_isblack == false) {
|
||||
__w->m_isblack = true;
|
||||
__x_parent->m_isblack = false;
|
||||
_rb_tree_rotate_right(__x_parent, __root);
|
||||
__w = __x_parent->m_left;
|
||||
}
|
||||
if ((__w->m_right == 0 || __w->m_right->m_isblack == true) &&
|
||||
(__w->m_left == 0 || __w->m_left->m_isblack == true)) {
|
||||
__w->m_isblack = false;
|
||||
__x = __x_parent;
|
||||
__x_parent = __x_parent->m_parent;
|
||||
}
|
||||
else {
|
||||
if (__w->m_left == 0 || __w->m_left->m_isblack == true) {
|
||||
__w->m_right->m_isblack = true;
|
||||
__w->m_isblack = false;
|
||||
_rb_tree_rotate_left(__w, __root);
|
||||
__w = __x_parent->m_left;
|
||||
}
|
||||
__w->m_isblack = __x_parent->m_isblack;
|
||||
__x_parent->m_isblack = true;
|
||||
if (__w->m_left) __w->m_left->m_isblack = true;
|
||||
_rb_tree_rotate_right(__x_parent, __root);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (__x) __x->m_isblack = true;
|
||||
}
|
||||
return __y;
|
||||
}
|
||||
}
|
|
@ -10,7 +10,12 @@ namespace geode::base {
|
|||
}
|
||||
|
||||
#if defined(GEODE_IS_MACOS) || defined(GEODE_IS_ANDROID)
|
||||
|
||||
#include "gnustl-map.hpp"
|
||||
|
||||
namespace gd {
|
||||
using namespace geode::stl;
|
||||
|
||||
struct _internal_string {
|
||||
size_t m_len;
|
||||
size_t m_capacity;
|
||||
|
@ -48,18 +53,6 @@ namespace gd {
|
|||
_internal_string* m_data;
|
||||
};
|
||||
|
||||
struct _rb_tree_base {
|
||||
bool m_isblack;
|
||||
_rb_tree_base* m_parent;
|
||||
_rb_tree_base* m_left;
|
||||
_rb_tree_base* m_right;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct _rb_tree_node : public _rb_tree_base {
|
||||
T m_value;
|
||||
};
|
||||
|
||||
template <typename K, typename V>
|
||||
class GEODE_DLL map {
|
||||
protected:
|
||||
|
@ -69,26 +62,191 @@ namespace gd {
|
|||
|
||||
public:
|
||||
typedef _rb_tree_node<std::pair<K, V>>* _tree_node;
|
||||
typedef _rb_tree_iterator<std::pair<K, V>> iterator;
|
||||
|
||||
std::map<K, V> std();
|
||||
std::map<K, V> std() {
|
||||
return (std::map<K, V>)(*this);
|
||||
}
|
||||
|
||||
operator std::map<K, V>();
|
||||
operator std::map<K, V>() {
|
||||
auto iter_node = static_cast<_tree_node>(m_header.m_left);
|
||||
auto end_node = static_cast<_tree_node>(&m_header);
|
||||
std::map<K, V> out;
|
||||
for (; iter_node != end_node;
|
||||
iter_node = static_cast<_tree_node>(_rb_increment(iter_node))) {
|
||||
out[iter_node->m_value.first] = iter_node->m_value.second;
|
||||
}
|
||||
|
||||
operator std::map<K, V>() const;
|
||||
return out;
|
||||
}
|
||||
|
||||
void insert(_tree_node x, _tree_node p, std::pair<K, V> const& val);
|
||||
operator std::map<K, V>() const {
|
||||
auto iter_node = static_cast<_tree_node>(m_header.m_left);
|
||||
auto end_node = (_tree_node)(&m_header);
|
||||
std::map<K, V> out;
|
||||
for (; iter_node != end_node;
|
||||
iter_node = static_cast<_tree_node>(_rb_increment(iter_node))) {
|
||||
out[iter_node->m_value.first] = iter_node->m_value.second;
|
||||
}
|
||||
|
||||
void insert_pair(std::pair<K, V> const& val);
|
||||
return out;
|
||||
}
|
||||
|
||||
map(std::map<K, V> input);
|
||||
void insert(_tree_node x, _tree_node p, std::pair<K, V> const& val) {
|
||||
bool insert_left =
|
||||
(x != 0 || p == static_cast<_tree_node>(&m_header) || val.first < p->m_value.first);
|
||||
|
||||
void erase(_tree_node x);
|
||||
_tree_node z = new _rb_tree_node<std::pair<K, V>>();
|
||||
z->m_value = val;
|
||||
|
||||
map(map const& lol);
|
||||
_rb_insert_rebalance(insert_left, z, p, m_header);
|
||||
++m_nodecount;
|
||||
}
|
||||
|
||||
map();
|
||||
void insert_pair(std::pair<K, V> const& val) {
|
||||
_tree_node x = static_cast<_tree_node>(m_header.m_parent);
|
||||
_tree_node y = static_cast<_tree_node>(&m_header);
|
||||
bool comp = true;
|
||||
while (x != 0) {
|
||||
y = x;
|
||||
comp = val.first < x->m_value.first;
|
||||
x = comp ? static_cast<_tree_node>(x->m_left) : static_cast<_tree_node>(x->m_right);
|
||||
}
|
||||
auto iter = y;
|
||||
|
||||
~map();
|
||||
if (comp) {
|
||||
if (iter == static_cast<_tree_node>(m_header.m_left)) {
|
||||
insert(x, y, val);
|
||||
}
|
||||
else {
|
||||
iter = static_cast<_tree_node>(_rb_decrement(iter));
|
||||
}
|
||||
}
|
||||
if (iter->m_value.first < val.first) {
|
||||
insert(x, y, val);
|
||||
}
|
||||
}
|
||||
|
||||
map(std::map<K, V> input) {
|
||||
m_header.m_isblack = false;
|
||||
m_header.m_parent = 0;
|
||||
m_header.m_left = &m_header;
|
||||
m_header.m_right = &m_header;
|
||||
|
||||
for (auto i : input) {
|
||||
insert_pair(i);
|
||||
}
|
||||
}
|
||||
|
||||
void erase(_tree_node x) {
|
||||
while (x != 0) {
|
||||
erase(static_cast<_tree_node>(x->m_right));
|
||||
auto y = static_cast<_tree_node>(x->m_left);
|
||||
delete y;
|
||||
x = y;
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<iterator, iterator> equal_range(const K& __k) {
|
||||
return std::pair<iterator, iterator>(lower_bound(__k), upper_bound(__k));
|
||||
}
|
||||
|
||||
size_t erase(K const& __x) {
|
||||
std::pair<iterator, iterator> __p = equal_range(__x);
|
||||
size_t __n = 0;
|
||||
distance(__p.first, __p.second, __n);
|
||||
erase(__p.first, __p.second);
|
||||
return __n;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
erase(static_cast<_tree_node>(m_header.m_parent));
|
||||
m_header.m_parent = 0;
|
||||
m_header.m_left = &m_header;
|
||||
m_header.m_right = &m_header;
|
||||
m_nodecount = 0;
|
||||
}
|
||||
|
||||
void erase(iterator __first, iterator __last) {
|
||||
if (__first == begin() && __last == end()) {
|
||||
clear();
|
||||
}
|
||||
else {
|
||||
while (__first != __last) {
|
||||
erase(__first++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void erase(iterator __pos) {
|
||||
_tree_node __y = static_cast<_tree_node>(_rb_rebalance_for_erase(
|
||||
__pos.m_node, m_header.m_parent, m_header.m_left, m_header.m_right));
|
||||
delete __y;
|
||||
--m_nodecount;
|
||||
}
|
||||
|
||||
iterator begin() noexcept {
|
||||
return iterator(m_header.m_left);
|
||||
}
|
||||
|
||||
iterator end() noexcept {
|
||||
return iterator(&m_header);
|
||||
}
|
||||
|
||||
bool empty() const noexcept {
|
||||
return m_nodecount == 0;
|
||||
}
|
||||
|
||||
size_t size() const noexcept {
|
||||
return m_nodecount;
|
||||
}
|
||||
|
||||
iterator lower_bound(K const& __x) {
|
||||
_tree_node __j = static_cast<_tree_node>(m_header.m_left);
|
||||
_tree_node __k = static_cast<_tree_node>(&m_header);
|
||||
while (__j != nullptr) {
|
||||
if (!compare(__j->m_value.first, __x)) {
|
||||
__k = __j;
|
||||
__j = static_cast<_tree_node>(__j->m_left);
|
||||
}
|
||||
else {
|
||||
__j = static_cast<_tree_node>(__j->m_right);
|
||||
}
|
||||
}
|
||||
return iterator(__k);
|
||||
}
|
||||
|
||||
iterator upper_bound(K const& __x) {
|
||||
_tree_node __j = static_cast<_tree_node>(m_header.m_left);
|
||||
_tree_node __k = static_cast<_tree_node>(&m_header);
|
||||
while (__j != nullptr) {
|
||||
if (compare(__x, __j->m_value.first)) {
|
||||
__k = __j;
|
||||
__j = static_cast<_tree_node>(__j->m_left);
|
||||
}
|
||||
else {
|
||||
__j = static_cast<_tree_node>(__j->m_right);
|
||||
}
|
||||
}
|
||||
return iterator(__k);
|
||||
}
|
||||
|
||||
iterator find(K const& __x) {
|
||||
iterator __j = lower_bound(__x);
|
||||
return (__j == end() || compare(__x, (*__j).first)) ? end() : __j;
|
||||
}
|
||||
|
||||
size_t count(K const& __x) {
|
||||
return find(__x) != end() ? 1 : 0;
|
||||
}
|
||||
|
||||
map(map const& lol) : map(std::map<K, V>(lol)) {}
|
||||
|
||||
map() : map(std::map<K, V>()) {}
|
||||
|
||||
~map() {
|
||||
erase(static_cast<_tree_node>(m_header.m_parent));
|
||||
}
|
||||
};
|
||||
|
||||
// template <class Type>
|
||||
|
|
|
@ -101,9 +101,9 @@ struct FileUtilsUpdatePaths : Modify<FileUtilsUpdatePaths, CCFileUtils> {
|
|||
// this filename in particular is never cached because its not actually present anywhere.
|
||||
// this is only an issue because cocos itself requests the full path for this in CCSprite,
|
||||
// and with a lot of search paths (specially ones added by geode), this can cause a significant amount of lag.
|
||||
if (filename == "cc_2x2_white_image"sv) {
|
||||
return "cc_2x2_white_image"s;
|
||||
}
|
||||
// if (filename == "cc_2x2_white_image"sv) {
|
||||
// return "cc_2x2_white_image"s;
|
||||
// }
|
||||
|
||||
return CCFileUtils::fullPathForFilename(filename, unk);
|
||||
}
|
||||
|
|
|
@ -57,241 +57,7 @@ namespace gd {
|
|||
return std::string(*this) == std::string(other);
|
||||
}
|
||||
|
||||
static void _rb_tree_rotate_left(_rb_tree_base* const x, _rb_tree_base*& root) {
|
||||
_rb_tree_base* const y = x->m_right;
|
||||
|
||||
x->m_right = y->m_left;
|
||||
if (y->m_left != 0) y->m_left->m_parent = x;
|
||||
y->m_parent = x->m_parent;
|
||||
|
||||
if (x == root) root = y;
|
||||
else if (x == x->m_parent->m_left) x->m_parent->m_left = y;
|
||||
else x->m_parent->m_right = y;
|
||||
y->m_left = x;
|
||||
x->m_parent = y;
|
||||
}
|
||||
|
||||
static void _rb_tree_rotate_right(_rb_tree_base* const x, _rb_tree_base*& root) {
|
||||
_rb_tree_base* const y = x->m_left;
|
||||
|
||||
x->m_left = y->m_right;
|
||||
if (y->m_right != 0) y->m_right->m_parent = x;
|
||||
y->m_parent = x->m_parent;
|
||||
|
||||
if (x == root) root = y;
|
||||
else if (x == x->m_parent->m_right) x->m_parent->m_right = y;
|
||||
else x->m_parent->m_left = y;
|
||||
y->m_right = x;
|
||||
x->m_parent = y;
|
||||
}
|
||||
|
||||
static void _rb_insert_rebalance(
|
||||
bool const insert_left, _rb_tree_base* x, _rb_tree_base* p, _rb_tree_base& header
|
||||
) {
|
||||
_rb_tree_base*& root = header.m_parent;
|
||||
|
||||
x->m_parent = p;
|
||||
x->m_left = 0;
|
||||
x->m_right = 0;
|
||||
x->m_isblack = false;
|
||||
|
||||
if (insert_left) {
|
||||
p->m_left = x;
|
||||
|
||||
if (p == &header) {
|
||||
header.m_parent = x;
|
||||
header.m_right = x;
|
||||
}
|
||||
else if (p == header.m_left) {
|
||||
header.m_left = x;
|
||||
}
|
||||
}
|
||||
else {
|
||||
p->m_right = x;
|
||||
|
||||
if (p == header.m_right) {
|
||||
header.m_right = x;
|
||||
}
|
||||
}
|
||||
|
||||
while (x != root && x->m_parent->m_isblack == false) {
|
||||
_rb_tree_base* const xpp = x->m_parent->m_parent;
|
||||
|
||||
if (x->m_parent == xpp->m_left) {
|
||||
_rb_tree_base* const y = xpp->m_right;
|
||||
if (y && y->m_isblack == false) {
|
||||
x->m_parent->m_isblack = true;
|
||||
y->m_isblack = true;
|
||||
xpp->m_isblack = false;
|
||||
x = xpp;
|
||||
}
|
||||
else {
|
||||
if (x == x->m_parent->m_right) {
|
||||
x = x->m_parent;
|
||||
_rb_tree_rotate_left(x, root);
|
||||
}
|
||||
x->m_parent->m_isblack = true;
|
||||
xpp->m_isblack = false;
|
||||
_rb_tree_rotate_right(xpp, root);
|
||||
}
|
||||
}
|
||||
else {
|
||||
_rb_tree_base* const y = xpp->m_left;
|
||||
if (y && y->m_isblack == false) {
|
||||
x->m_parent->m_isblack = true;
|
||||
y->m_isblack = true;
|
||||
xpp->m_isblack = false;
|
||||
x = xpp;
|
||||
}
|
||||
else {
|
||||
if (x == x->m_parent->m_left) {
|
||||
x = x->m_parent;
|
||||
_rb_tree_rotate_right(x, root);
|
||||
}
|
||||
x->m_parent->m_isblack = true;
|
||||
xpp->m_isblack = false;
|
||||
_rb_tree_rotate_left(xpp, root);
|
||||
}
|
||||
}
|
||||
}
|
||||
root->m_isblack = true;
|
||||
}
|
||||
|
||||
static _rb_tree_base* _rb_increment(_rb_tree_base* __x) throw() {
|
||||
if (__x->m_right != 0) {
|
||||
__x = __x->m_right;
|
||||
while (__x->m_left != 0)
|
||||
__x = __x->m_left;
|
||||
}
|
||||
else {
|
||||
_rb_tree_base* __y = __x->m_parent;
|
||||
while (__x == __y->m_right) {
|
||||
__x = __y;
|
||||
__y = __y->m_parent;
|
||||
}
|
||||
if (__x->m_right != __y) __x = __y;
|
||||
}
|
||||
return __x;
|
||||
}
|
||||
|
||||
static _rb_tree_base* _rb_decrement(_rb_tree_base* __x) throw() {
|
||||
if (!__x->m_isblack && __x->m_parent->m_parent == __x) __x = __x->m_right;
|
||||
else if (__x->m_left != 0) {
|
||||
_rb_tree_base* __y = __x->m_left;
|
||||
while (__y->m_right != 0)
|
||||
__y = __y->m_right;
|
||||
__x = __y;
|
||||
}
|
||||
else {
|
||||
_rb_tree_base* __y = __x->m_parent;
|
||||
while (__x == __y->m_left) {
|
||||
__x = __y;
|
||||
__y = __y->m_parent;
|
||||
}
|
||||
__x = __y;
|
||||
}
|
||||
return __x;
|
||||
}
|
||||
|
||||
template <class K, class V>
|
||||
std::map<K, V> map<K, V>::std() {
|
||||
return (std::map<K, V>)(*this);
|
||||
}
|
||||
|
||||
template <class K, class V>
|
||||
map<K, V>::operator std::map<K, V>() {
|
||||
auto iter_node = static_cast<_tree_node>(m_header.m_left);
|
||||
auto end_node = static_cast<_tree_node>(&m_header);
|
||||
std::map<K, V> out;
|
||||
for (; iter_node != end_node; iter_node = static_cast<_tree_node>(_rb_increment(iter_node))) {
|
||||
out[iter_node->m_value.first] = iter_node->m_value.second;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
template <class K, class V>
|
||||
map<K, V>::operator std::map<K, V>() const {
|
||||
auto iter_node = static_cast<_tree_node>(m_header.m_left);
|
||||
auto end_node = (_tree_node)(&m_header);
|
||||
std::map<K, V> out;
|
||||
for (; iter_node != end_node; iter_node = static_cast<_tree_node>(_rb_increment(iter_node))) {
|
||||
out[iter_node->m_value.first] = iter_node->m_value.second;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
template <class K, class V>
|
||||
void map<K, V>::insert(_tree_node x, _tree_node p, std::pair<K, V> const& val) {
|
||||
bool insert_left =
|
||||
(x != 0 || p == static_cast<_tree_node>(&m_header) || val.first < p->m_value.first);
|
||||
|
||||
_tree_node z = new _rb_tree_node<std::pair<K, V>>();
|
||||
z->m_value = val;
|
||||
|
||||
_rb_insert_rebalance(insert_left, z, p, m_header);
|
||||
++m_nodecount;
|
||||
}
|
||||
|
||||
template <class K, class V>
|
||||
void map<K, V>::insert_pair(std::pair<K, V> const& val) {
|
||||
_tree_node x = static_cast<_tree_node>(m_header.m_parent);
|
||||
_tree_node y = static_cast<_tree_node>(&m_header);
|
||||
bool comp = true;
|
||||
while (x != 0) {
|
||||
y = x;
|
||||
comp = val.first < x->m_value.first;
|
||||
x = comp ? static_cast<_tree_node>(x->m_left) : static_cast<_tree_node>(x->m_right);
|
||||
}
|
||||
auto iter = y;
|
||||
|
||||
if (comp) {
|
||||
if (iter == static_cast<_tree_node>(m_header.m_left)) {
|
||||
insert(x, y, val);
|
||||
}
|
||||
else {
|
||||
iter = static_cast<_tree_node>(_rb_decrement(iter));
|
||||
}
|
||||
}
|
||||
if (iter->m_value.first < val.first) {
|
||||
insert(x, y, val);
|
||||
}
|
||||
}
|
||||
|
||||
template <class K, class V>
|
||||
map<K, V>::map(std::map<K, V> input) {
|
||||
m_header.m_isblack = false;
|
||||
m_header.m_parent = 0;
|
||||
m_header.m_left = &m_header;
|
||||
m_header.m_right = &m_header;
|
||||
|
||||
for (auto i : input) {
|
||||
insert_pair(i);
|
||||
}
|
||||
}
|
||||
|
||||
template <class K, class V>
|
||||
void map<K, V>::erase(_tree_node x) {
|
||||
while (x != 0) {
|
||||
erase(static_cast<_tree_node>(x->m_right));
|
||||
auto y = static_cast<_tree_node>(x->m_left);
|
||||
delete y;
|
||||
x = y;
|
||||
}
|
||||
}
|
||||
|
||||
template <class K, class V>
|
||||
map<K, V>::map(map const& lol) : map(std::map<K, V>(lol)) {}
|
||||
|
||||
template <class K, class V>
|
||||
map<K, V>::map() : map(std::map<K, V>()) {}
|
||||
|
||||
template <class K, class V>
|
||||
map<K, V>::~map() {
|
||||
erase(static_cast<_tree_node>(m_header.m_parent));
|
||||
}
|
||||
|
||||
// TODO: these need to stay for old mods linking against geode <1.2.0
|
||||
template class map<int, int>;
|
||||
template class map<gd::string, gd::string>;
|
||||
template class map<gd::string, bool>;
|
||||
|
|
Loading…
Reference in a new issue