From db02c3dd1a20254a716d6c6dd92dfe76eeb5b66b Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sun, 27 Aug 2023 19:34:33 +0300 Subject: [PATCH] macos map add things --- loader/include/Geode/c++stl/gnustl-map.hpp | 347 +++++++++++++++++++++ loader/include/Geode/c++stl/gnustl.hpp | 202 ++++++++++-- loader/src/cocos2d-ext/CCFileUtils.cpp | 6 +- loader/src/platform/mac/gdstdlib.cpp | 236 +------------- 4 files changed, 531 insertions(+), 260 deletions(-) create mode 100644 loader/include/Geode/c++stl/gnustl-map.hpp diff --git a/loader/include/Geode/c++stl/gnustl-map.hpp b/loader/include/Geode/c++stl/gnustl-map.hpp new file mode 100644 index 00000000..91f974e5 --- /dev/null +++ b/loader/include/Geode/c++stl/gnustl-map.hpp @@ -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 + 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 + struct _rb_tree_iterator { + typedef T value_type; + typedef T& reference; + typedef T* pointer; + + typedef _rb_tree_iterator _Self; + typedef _rb_tree_base* _Base_ptr; + typedef _rb_tree_node* _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; + } +} \ No newline at end of file diff --git a/loader/include/Geode/c++stl/gnustl.hpp b/loader/include/Geode/c++stl/gnustl.hpp index 3f793382..8508d339 100644 --- a/loader/include/Geode/c++stl/gnustl.hpp +++ b/loader/include/Geode/c++stl/gnustl.hpp @@ -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 - struct _rb_tree_node : public _rb_tree_base { - T m_value; - }; - template class GEODE_DLL map { protected: @@ -69,26 +62,191 @@ namespace gd { public: typedef _rb_tree_node>* _tree_node; + typedef _rb_tree_iterator> iterator; - std::map std(); + std::map std() { + return (std::map)(*this); + } - operator std::map(); + operator std::map() { + auto iter_node = static_cast<_tree_node>(m_header.m_left); + auto end_node = static_cast<_tree_node>(&m_header); + std::map 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() const; + return out; + } - void insert(_tree_node x, _tree_node p, std::pair const& val); + operator std::map() const { + auto iter_node = static_cast<_tree_node>(m_header.m_left); + auto end_node = (_tree_node)(&m_header); + std::map 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 const& val); + return out; + } - map(std::map input); + void insert(_tree_node x, _tree_node p, std::pair 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>(); + 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 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 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 equal_range(const K& __k) { + return std::pair(lower_bound(__k), upper_bound(__k)); + } + + size_t erase(K const& __x) { + std::pair __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(lol)) {} + + map() : map(std::map()) {} + + ~map() { + erase(static_cast<_tree_node>(m_header.m_parent)); + } }; // template diff --git a/loader/src/cocos2d-ext/CCFileUtils.cpp b/loader/src/cocos2d-ext/CCFileUtils.cpp index 67796df9..39ce7542 100644 --- a/loader/src/cocos2d-ext/CCFileUtils.cpp +++ b/loader/src/cocos2d-ext/CCFileUtils.cpp @@ -101,9 +101,9 @@ struct FileUtilsUpdatePaths : Modify { // 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); } diff --git a/loader/src/platform/mac/gdstdlib.cpp b/loader/src/platform/mac/gdstdlib.cpp index 69e62a49..0c508a74 100644 --- a/loader/src/platform/mac/gdstdlib.cpp +++ b/loader/src/platform/mac/gdstdlib.cpp @@ -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 - std::map map::std() { - return (std::map)(*this); - } - - template - map::operator std::map() { - auto iter_node = static_cast<_tree_node>(m_header.m_left); - auto end_node = static_cast<_tree_node>(&m_header); - std::map 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 - map::operator std::map() const { - auto iter_node = static_cast<_tree_node>(m_header.m_left); - auto end_node = (_tree_node)(&m_header); - std::map 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 - void map::insert(_tree_node x, _tree_node p, std::pair 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>(); - z->m_value = val; - - _rb_insert_rebalance(insert_left, z, p, m_header); - ++m_nodecount; - } - - template - void map::insert_pair(std::pair 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 - map::map(std::map 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 - void map::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 - map::map(map const& lol) : map(std::map(lol)) {} - - template - map::map() : map(std::map()) {} - - template - map::~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; template class map; template class map;