diff --git a/LEGO1/mxatomid.cpp b/LEGO1/mxatomid.cpp index 31619427..b946a2e9 100644 --- a/LEGO1/mxatomid.cpp +++ b/LEGO1/mxatomid.cpp @@ -18,13 +18,50 @@ MxAtomId::MxAtomId(const char *p_str, LookupMode p_mode) // OFFSET: LEGO1 0x100acfd0 MxAtomId::~MxAtomId() { - // TODO + Destroy(); +} + +// OFFSET: LEGO1 0x100acfe0 +void MxAtomId::Destroy() +{ + if (*m_internal == '\0') + return; + + if (!MxOmni::GetInstance()) + return; + + if (!AtomIdTree()) + return; + + TreeValue value = TreeValue(m_internal); + TreeValue *p = &value; + + // 100ad052 + MxBinaryTree *tree = AtomIdTree(); + TreeNode *root = tree->m_root; + + // should inline Search but NOT TreeValueCompare + TreeNode *node = tree->Search(p); + + TreeNode *ass = node; + if (node == root->m_parent || TreeValueCompare(p, node->m_value)) { + ass = root->m_parent; + } + + node->m_value->RefCountDec(); } // OFFSET: LEGO1 0x100ad1c0 -MxAtomId &MxAtomId::operator=(const MxAtomId &id) +MxAtomId &MxAtomId::operator=(const MxAtomId &atomId) { // TODO + const char *temp = m_internal; + if (m_internal) + Destroy(); + + if (atomId.m_internal && MxOmni::GetInstance() && AtomIdTree()) + try_to_open(temp, LookupMode_Exact); + return *this; } @@ -44,16 +81,17 @@ TreeValue *MxAtomId::try_to_open(const char *p_str, LookupMode p_mode) break; } + // LAB_100ad2a1 MxBinaryTree *tree = AtomIdTree(); // get the closest node that matches the given value + // should NOT inline node = tree->Search(value); // pointer reuse??? TreeNode *ptr_reuse = node; // is the node an exact match? - if (tree->m_root == node || - strcmp(value->m_str.GetData(), node->m_value->m_str.GetData()) > 0) { + if (tree->m_root == node || TreeValueCompare(value, node->m_value)) { ptr_reuse = tree->m_root; } @@ -70,3 +108,10 @@ TreeValue *MxAtomId::try_to_open(const char *p_str, LookupMode p_mode) return value; } + +// OFFSET: LEGO1 0x100ad7e0 +void MxAtomId::Clear() +{ + Destroy(); + m_internal = NULL; +} diff --git a/LEGO1/mxatomid.h b/LEGO1/mxatomid.h index 71c9f434..ac154c69 100644 --- a/LEGO1/mxatomid.h +++ b/LEGO1/mxatomid.h @@ -33,6 +33,8 @@ class MxAtomId // TODO: belongs here? TreeValue *try_to_open(const char *, LookupMode); + void Destroy(); + void Clear(); private: const char *m_internal; diff --git a/LEGO1/mxbinarytree.cpp b/LEGO1/mxbinarytree.cpp index 9e6eed81..7622a2bf 100644 --- a/LEGO1/mxbinarytree.cpp +++ b/LEGO1/mxbinarytree.cpp @@ -3,6 +3,12 @@ // 0x101013f0 TreeNode *MxBinaryTree::g_Node_Nil = NULL; +// OFFSET: LEGO1 0x100ad170 +TreeValue::~TreeValue() +{ + // nothing. +} + inline void MxBinaryTree::LeftRotate(TreeNode *x) { TreeNode *y = x->m_child1; @@ -14,23 +20,22 @@ inline void MxBinaryTree::LeftRotate(TreeNode *x) y->m_parent = x->m_parent; if (m_root->m_parent != x) { - if (x == x->m_parent->m_child0) { - x->m_parent->m_child0 = y; - y->m_child0 = x; //? - x->m_parent = y; //? - } else { + if (x != x->m_parent->m_child0) { x->m_parent->m_child1 = y; - y->m_child1 = x; //? - x->m_parent = y; //? + y->m_child0 = x; + x->m_parent = y; + } else { + x->m_parent->m_child0 = y; + y->m_child0 = x; + x->m_parent = y; } } else { - // ? + m_root->m_parent->m_child0 = y; y->m_child0 = x; x->m_parent = y; } } - inline void MxBinaryTree::RightRotate(TreeNode *x) { TreeNode *y = x->m_child0; @@ -42,17 +47,17 @@ inline void MxBinaryTree::RightRotate(TreeNode *x) y->m_parent = x->m_parent; if (m_root->m_parent != x) { - if (x == x->m_parent->m_child1) { - x->m_parent->m_child1 = y; - y->m_child1 = x; //? - x->m_parent = y; //? - } else { + if (x != x->m_parent->m_child1) { x->m_parent->m_child0 = y; - y->m_child0 = x; //? - x->m_parent = y; //? + y->m_child1 = x; + x->m_parent = y; + } else { + x->m_parent->m_child1 = y; + y->m_child1 = x; + x->m_parent = y; } } else { - //? + m_root->m_parent->m_child1 = y; y->m_child1 = x; x->m_parent = y; } @@ -93,26 +98,24 @@ void mini_walk(TreeNode* &p_node) } // OFFSET: LEGO1 0x100ad4d0 -void MxBinaryTree::FUN_100ad4d0(TreeNode **p_output, TreeNode *p_leaf, TreeNode *p_parent, TreeValue *&p_value) +void MxBinaryTree::Insert(TreeNode **p_output, TreeNode *p_leaf, TreeNode *p_parent, TreeValue *&p_value) { - TreeNode *node = new TreeNode(p_parent, NODE_COLOR_RED); + TreeNode *node = newTreeNode(p_parent, NODE_COLOR_RED); node->m_child0 = g_Node_Nil; node->m_child1 = g_Node_Nil; // TODO: ??? - if (node->m_value) { + if (&node->m_value) node->m_value = p_value; - } - this->m_p3++; // node count? + this->m_nodeCount++; // if tree is NOT empty // if param_2 is tree_nil (always true I think?) // - if (this->m_root != p_parent + if (m_root != p_parent && p_leaf == MxBinaryTree::g_Node_Nil - && strcmp(p_value->m_str.GetData(), - p_parent->m_value->m_str.GetData()) <= 0) { + && TreeValueCompare(p_value, p_parent->m_value)) { p_parent->m_child1 = node; if (m_root->m_child1 == p_parent) @@ -120,8 +123,9 @@ void MxBinaryTree::FUN_100ad4d0(TreeNode **p_output, TreeNode *p_leaf, TreeNode } else { p_parent->m_child0 = node; - if (m_root != p_parent && m_root->m_child0 == p_parent) { - m_root->m_child0 = p_parent; + if (m_root != p_parent) { + if (m_root->m_child0 == p_parent) + m_root->m_child0 = node; } else { m_root->m_parent = node; m_root->m_child1 = node; @@ -129,7 +133,7 @@ void MxBinaryTree::FUN_100ad4d0(TreeNode **p_output, TreeNode *p_leaf, TreeNode } // LAB_100ad593 - // rebalance?? + // rebalance the tree TreeNode *cur = node; while (m_root->m_parent != cur) { TreeNode *parent = cur->m_parent; @@ -137,12 +141,10 @@ void MxBinaryTree::FUN_100ad4d0(TreeNode **p_output, TreeNode *p_leaf, TreeNode if (parent->m_color != NODE_COLOR_RED) break; - TreeNode *grandparent = parent->m_parent; - TreeNode *uncle = grandparent->m_child0; - + TreeNode *uncle = parent->m_parent->m_child0; if (uncle == parent) { // wrong uncle - uncle = grandparent->m_child1; + uncle = parent->m_parent->m_child1; if (uncle->m_color != NODE_COLOR_RED) { @@ -150,23 +152,6 @@ void MxBinaryTree::FUN_100ad4d0(TreeNode **p_output, TreeNode *p_leaf, TreeNode if (parent->m_child1 == cur) { cur = parent; LeftRotate(cur); - // rotate. - /* - parent->m_child1 = parent->m_child1->m_child0; - - // 100ad5e2 - if (parent->m_child1 != g_Node_Nil) - parent->m_child1->m_parent = cur; - - parent->m_child1->m_parent = grandparent; - if (m_root->m_parent == cur || grandparent->m_child0 == cur) - grandparent->m_child1 = parent; - else - grandparent->m_child0 = parent; - - parent->m_child0 = cur; - grandparent->m_child0 = parent; - */ } // LAB_100ad60f @@ -210,10 +195,7 @@ TreeNode *MxBinaryTree::Search(TreeValue*& p_value) TreeNode *t_node = node_match->m_parent; while (t_node != g_Node_Nil) { - int result = strcmp(t_node->m_value->m_str.GetData(), p_value->m_str.GetData()); - - if (result <= 0) { - // if strings equal or less than search string + if (!TreeValueCompare(t_node->m_value, p_value)) { // closest match? // it either does match or is where we will insert the new node. node_match = t_node; diff --git a/LEGO1/mxbinarytree.h b/LEGO1/mxbinarytree.h index ac02c1e5..b0a8abef 100644 --- a/LEGO1/mxbinarytree.h +++ b/LEGO1/mxbinarytree.h @@ -15,6 +15,7 @@ class TreeValue { m_str = p_str; m_t0 = 0; } + ~TreeValue(); void RefCountInc(); void RefCountDec(); @@ -27,12 +28,6 @@ class TreeValue { // SIZE 0x14 class TreeNode { public: - TreeNode(TreeNode *p_parent, int p_color) - { - m_parent = p_parent; - m_color = p_color; - } - TreeNode *m_child0; // +0 // string sorts after TreeNode *m_parent; // +4 // parent node TreeNode *m_child1; // +8 // string sorts before @@ -40,6 +35,21 @@ class TreeNode { int m_color; // +10 // BLACK or RED. }; +// TODO: helper to avoid using a non-default constructor +inline TreeNode *newTreeNode(TreeNode *p_parent, int p_color) +{ + TreeNode *t = new TreeNode(); + t->m_parent = p_parent; + t->m_color = p_color; + return t; +} + +// OFFSET: LEGO1 0x100ad120 +inline int TreeValueCompare(TreeValue *&p_val0, TreeValue *&p_val1) +{ + return strcmp(p_val0->m_str.GetData(), p_val1->m_str.GetData()) > 0; +} + // SIZE 0x10 class MxBinaryTree { @@ -49,23 +59,23 @@ class MxBinaryTree MxBinaryTree() { if (!g_Node_Nil) { - g_Node_Nil = new TreeNode(NULL, NODE_COLOR_BLACK); + g_Node_Nil = newTreeNode(NULL, NODE_COLOR_BLACK); g_Node_Nil->m_child0 = NULL; g_Node_Nil->m_child1 = NULL; } - m_root = new TreeNode(g_Node_Nil, NODE_COLOR_RED); + m_root = newTreeNode(g_Node_Nil, NODE_COLOR_RED); } void LeftRotate(TreeNode *); void RightRotate(TreeNode *); - void FUN_100ad4d0(TreeNode **, TreeNode *, TreeNode *, TreeValue *&); + void Insert(TreeNode **, TreeNode *, TreeNode *, TreeValue *&); TreeNode *Search(TreeValue *&); int m_p0; // +0 TreeNode *m_root; // +4 int m_p2; // +8 - int m_p3; // +c + int m_nodeCount; // +c }; #endif //MXBINARYTREE_H \ No newline at end of file