/// Function name : compareAVLTreeNodeWithValues // Description : Compares a node in an AVLTree against a specified set of values /// The number of values must match the number of tree sort keys // // CONST AVL_TREE* pTree : [in] AVLTree containing the nodes // CONST LPARAM pNodeData : [in] Data of the node to compare // ... ... : [in] Value to compare node against // // Return Value : CR_LESSER : The value is less than the node // CR_EQUAL : The value is equal to the node // CR_GREATER : The value is more than the node // COMPARISON_RESULT compareAVLTreeNodeWithValues(CONST AVL_TREE* pTree, CONST LPARAM pNodeData, LPARAM xValue1, LPARAM xValue2, LPARAM xValue3) { COMPARISON_RESULT eResult; // Comparison result CONST AVL_TREE_KEY* pCurrentKey; // Convenience pointer LPARAM xNodeProperty, // Extracted property of the input node xSearchValues[3] = {xValue1, xValue2, xValue3}; // Input values // Prepare eResult = CR_EQUAL; /// Iterate through sort keys for (UINT iKey = 0; (eResult == CR_EQUAL) AND (iKey < pTree->iKeyCount); iKey++) { // Prepare pCurrentKey = pTree->pSortKeys[iKey]; // Extract appropriate property value from node xNodeProperty = extractObjectProperty(pTree, pNodeData, pCurrentKey->eSorting); /// [COMPARISON] Compare property against current search value switch (pCurrentKey->eType) { case AP_STRING_CASE: eResult = (COMPARISON_RESULT)StrCmp((TCHAR*)xNodeProperty, (TCHAR*)xSearchValues[iKey]); break; case AP_STRING: eResult = (COMPARISON_RESULT)StrCmpI((TCHAR*)xNodeProperty, (TCHAR*)xSearchValues[iKey]); break; case AP_INTEGER: eResult = (COMPARISON_RESULT)utilCompareIntegers((INT)xSearchValues[iKey], (INT)xNodeProperty); break; } /// [DIRECTION] Flip the result for descending ordering if (pCurrentKey->eDirection == AO_DESCENDING) eResult = (COMPARISON_RESULT)(eResult * -1); } // Return result return eResult; }
WCHAR* VConverter::extractObjectVersion(const WCHAR* buffer) { WCHAR* buffCopy = NULL; size_t buffCopyLen = 0; WCHAR* tmp = extractObjectProperty(buffer, TEXT("VERSION"), buffCopy, buffCopyLen); WCHAR* ret = wstrdup(tmp); if (buffCopy) { delete [] buffCopy; } buffCopyLen = 0; return ret; }
/// Function name : insertObjectIntoAVLTree // Description : Inserts an object into an AVL tree at the appropriate position, given the tree's sort key(s). /// -> Rebalances the tree as necessary. /// -> Inserting a new node invalidates the indexing. // // AVL_TREE* pTree : [in] Target tree // LPARAM pNewObject : [in] Object to be to inserted // AVL_TREE_NODE* pCurrentNode : [in] [optional] Node currently being processed /// Must be NULL on initial call // // Return Type : TRUE if inserted, FALSE if it was already present // BearScriptAPI BOOL insertObjectIntoAVLTree(AVL_TREE* pTree, LPARAM pNewObject, AVL_TREE_NODE* pCurrentNode) { BOOL bResult; // Operation result, defaults to FALSE LPARAM xSearchValues[3]; // Prepare bResult = FALSE; /// [CHECK] Is Tree Empty? if (pTree->pRoot == NULL) { // [SUCCESS] Insert node as new ROOT and return TRUE pTree->pRoot = createAVLTreeNode(pTree, NULL, pNewObject); return TRUE; } // [CHECK] Is this the initial call? else if (pCurrentNode == NULL) // [SUCCESS] Start search at ROOT pCurrentNode = pTree->pRoot; // Extract search values from input object for (UINT iKey = 0; iKey < pTree->iKeyCount; iKey++) xSearchValues[iKey] = extractObjectProperty(pTree, pNewObject, pTree->pSortKeys[iKey]->eSorting); /// [COMPARE] Compare current node with values switch (compareAVLTreeNodeWithValues(pTree, pCurrentNode->pData, xSearchValues[0], xSearchValues[1], xSearchValues[2])) { /// [LESS THAN] - Insert/Recurse into left child case CR_LESSER: // [CHECK] Does LEFT CHILD already exist? if (pCurrentNode->pLeft) // [FAILURE] Attempt to insert into left child bResult = insertObjectIntoAVLTree(pTree, pNewObject, pCurrentNode->pLeft); else { // [SUCCESS] Insert object in a new tree node here pCurrentNode->pLeft = createAVLTreeNode(pTree, pCurrentNode, pNewObject); // Return TRUE bResult = TRUE; } break; /// [GREATER THAN] - Insert/Recurse into right child case CR_GREATER: // Examine the right child if (pCurrentNode->pRight) // [EXISTS] Pass to right child bResult = insertObjectIntoAVLTree(pTree, pNewObject, pCurrentNode->pRight); else { // [EMPTY] Insert object into a new tree node here pCurrentNode->pRight = createAVLTreeNode(pTree, pCurrentNode, pNewObject); // Return TRUE bResult = TRUE; } break; } // [CHECK] Has tree been changed? if (bResult) { // Remove the indexing flag pTree->bIndexed = FALSE; // Recalculate node height pCurrentNode->iHeight = calculateAVLTreeNodeHeight(pCurrentNode); // Ensure subtree is balanced ensureSubTreeIsBalanced(pTree, pCurrentNode, AC_INSERTION); } // Return TRUE if object was inserted, FALSE otherwise return bResult; }