macos map add things

This commit is contained in:
altalk23 2023-08-27 19:34:33 +03:00
parent 7836e60b86
commit db02c3dd1a
4 changed files with 531 additions and 260 deletions

View 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;
}
}

View file

@ -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>

View file

@ -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);
}

View file

@ -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>;