| /////////////////////////////////////////////////////////////////////////////// |
| // // |
| // Copyright (c) 2000-2019 Ericsson Telecom AB // |
| // // |
| // All rights reserved. This program and the accompanying materials // |
| // are made available under the terms of the Eclipse Public License v2.0 // |
| // which accompanies this distribution, and is available at // |
| // https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html // |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| /////////////////////////////////////////////////////////// |
| // Module: EPTF_CLL_RBtreeInteger_PrivateFunctions |
| // |
| // Purpose: |
| // This module contains private functions for TTCN-3 integer Red-Black tree implementation. |
| // These functions are not to be used by the user, only by other functions. |
| // |
| // Module depends on: |
| // <EPTF_CLL_Common_Definitions> |
| // <EPTF_CLL_Common_Functions> |
| // <EPTF_CLL_RBtree_Definitions> |
| // <EPTF_CLL_RBtree_PrivateFunctions> |
| // |
| // Current Owner: |
| // Rita Kovacs (ERITKOV) |
| // |
| // Last Review Date: |
| // 2007-12-06 |
| /////////////////////////////////////////////////////////////// |
| |
| module EPTF_CLL_RBtreeInteger_PrivateFunctions { |
| |
| import from EPTF_CLL_Common_Definitions all; |
| import from EPTF_CLL_Common_Functions all; |
| import from EPTF_CLL_RBtree_Definitions all; |
| import from EPTF_CLL_RBtree_PrivateFunctions all; |
| |
| friend module EPTF_CLL_RBtreeInteger_Functions; |
| |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_RBTreeI_getIntegerElementIndexByKey |
| // |
| // Purpose: |
| // Function to get the given integer-identified event (node) from the tree. |
| // |
| // Parameters: |
| // pl_tree - *inout* <EPTF_Integer_RedBlackTree> - the up-to-date integer red-black-tree itself |
| // pl_key - *in* *integer* - node to get |
| // pl_indexFound - *out* *integer* - index of the tree node of the given key |
| // |
| // Return Value: |
| // boolean - success |
| /////////////////////////////////////////////////////////// |
| |
| friend function f_EPTF_RBTreeI_getIntegerElementIndexByKey(inout EPTF_Integer_RedBlackTree pl_tree, in integer pl_key, out integer pl_indexFound) return boolean { |
| var boolean vl_isFound := false; |
| var integer root := pl_tree.nodes[pl_tree.root].left; // the real root of the tree |
| var integer nil := pl_tree.nil; |
| |
| var integer vl_x := root; |
| while (vl_x != nil and not vl_isFound) { |
| if (pl_tree.integerKeyData[vl_x].key == pl_key) { |
| vl_isFound := true; |
| pl_indexFound := vl_x; |
| //log("DEBUG: [f_EPTF_RBTreeI_getIntegerElementIndexByKey] pl_indexFound: ",pl_indexFound); |
| } else { |
| if (pl_key < pl_tree.integerKeyData[vl_x].key) { |
| // we go forward to left |
| vl_x := pl_tree.nodes[vl_x].left; |
| } else { |
| // we go forward to right |
| vl_x := pl_tree.nodes[vl_x].right; |
| } |
| } // else |
| } // while |
| |
| //log("DEBUG: [f_EPTF_RBTreeI_getIntegerElementIndexByKey] vl_isFound: ", vl_isFound); |
| return vl_isFound; |
| } // f_EPTF_RBTreeI_getIntegerElementIndexByKey |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_RBTreeI_insertIntegerNodeWithSameKey |
| // |
| // Purpose: |
| // Function to insert the given integer-identified event (node) to cluster chain. |
| // |
| // Parameters: |
| // pl_tree - *inout* <EPTF_Integer_RedBlackTree> - the up-to-date integer red-black-tree itself |
| // pl_newNodeIndex - *in* *integer* - index of the integer tree node to insert |
| // |
| // Return Value: |
| // boolean - success |
| /////////////////////////////////////////////////////////// |
| |
| private function f_EPTF_RBTreeI_insertIntegerNodeWithSameKey(inout EPTF_Integer_RedBlackTree pl_tree, in integer pl_newNodeIndex) return boolean { |
| |
| var boolean vl_result := false; |
| var integer vl_indexFound := -1; |
| if (f_EPTF_RBTreeI_getIntegerElementIndexByKey(pl_tree, pl_tree.integerKeyData[pl_newNodeIndex].key, vl_indexFound)) { |
| vl_result := true; |
| f_EPTF_RBTree_insertNodeWithSameKey(pl_tree.nodes, pl_newNodeIndex, vl_indexFound); |
| } |
| return vl_result; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_RBTreeI_insertInteger |
| // |
| // Purpose: |
| // Function to insert the given integer-identified event (node) to the tree. |
| // |
| // Parameters: |
| // pl_tree - *inout* <EPTF_Integer_RedBlackTree> - the up-to-date integer red-black-tree itself |
| // pl_x - *in* *integer* - index of the integer tree node to insert |
| // |
| // Return Value: |
| // boolean - success |
| /////////////////////////////////////////////////////////// |
| |
| friend function f_EPTF_RBTreeI_insertInteger(inout EPTF_Integer_RedBlackTree pl_tree, in integer pl_x) { |
| |
| // Storing number of elements |
| pl_tree.nOfElements := pl_tree.nOfElements + 1; |
| |
| // If the same key is exists, we append this node to a cluster |
| // and not to the tree. |
| if (f_EPTF_RBTreeI_insertIntegerNodeWithSameKey(pl_tree, pl_x)) { |
| return; |
| } |
| |
| f_EPTF_RBTreeI_helpIntegerTreeInsert(pl_tree, pl_x); |
| f_EPTF_RBTree_RBTreeInsert(pl_tree.nodes, pl_tree.root, pl_tree.nil, pl_x); |
| |
| f_EPTF_RBTreeI_checkMaxSize(%definitionId, pl_tree); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_RBTreeI_helpIntegerTreeInsert |
| // |
| // Purpose: |
| // Inserts z into the tree as if it were a regular binary tree using the algorithm described |
| // in _Introduction_To_Algorithms_ by Cormen et al. This function is only intended to be called |
| // by the <f_EPTF_RBTree_RBTreeInsert> function and not by the user. |
| // |
| // Parameters: |
| // pl_tree - *inout* <EPTF_Integer_RedBlackTree> - the up-to-date integer red-black-tree itself |
| // pl_z - *in* *integer* - index of the integer tree node to insert |
| // |
| // Return Value: |
| // (none) |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_RBTreeI_helpIntegerTreeInsert(inout EPTF_Integer_RedBlackTree pl_tree, in integer pl_z) { |
| var integer x := pl_tree.nodes[pl_tree.root].left; // real root node of the tree |
| var integer y := pl_tree.root; // sentinel |
| var integer nil := pl_tree.nil; |
| |
| // !!! ? These are not neccessary, because left and right already set during |
| // node creation -> CHECK !!! |
| pl_tree.nodes[pl_z].left := nil; |
| pl_tree.nodes[pl_z].right := nil; |
| |
| while (x != nil) { |
| y := x; |
| if (pl_tree.integerKeyData[x].key > pl_tree.integerKeyData[pl_z].key) { |
| x := pl_tree.nodes[x].left; |
| } else { |
| x := pl_tree.nodes[x].right; |
| } |
| } // while |
| |
| pl_tree.nodes[pl_z].parent := y; |
| |
| if ( (y == pl_tree.root) or |
| (pl_tree.integerKeyData[y].key > pl_tree.integerKeyData[pl_z].key) ) { |
| pl_tree.nodes[y].left := pl_z; |
| } else { |
| pl_tree.nodes[y].right := pl_z; |
| } |
| } // f_EPTF_RBTreeI_helpIntegerTreeInsert |
| |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_RBTreeI_getFreeSlotInteger |
| // |
| // Purpose: |
| // search for a free (unused or new) slot in integer tree |
| // |
| // Parameters: |
| // pl_tree - *inout* <EPTF_Integer_RedBlackTree> - the up-to-date integer red-black-tree |
| // |
| // Return Value: |
| // integer - leaf integer node's index |
| /////////////////////////////////////////////////////////// |
| |
| friend function f_EPTF_RBTreeI_getFreeSlotInteger(inout EPTF_Integer_RedBlackTree pl_tree) return integer { |
| return f_EPTF_RBTree_getFreeSlot( |
| pl_tree.nodes, |
| pl_tree.freeHead, |
| pl_tree.freeTail, |
| pl_tree.nodesCurMaxIndex |
| ); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_RBTreeI_destroyIntegerNode |
| // |
| // Purpose: |
| // deletes node from integer tree |
| // |
| // Parameters: |
| // pl_tree - *inout* <EPTF_Integer_RedBlackTree> - the up-to-date integer red-black-tree |
| // pl_z - *in* *integer* - index of the integer tree node to delete |
| // |
| // Return Value: |
| // (none) |
| /////////////////////////////////////////////////////////// |
| |
| friend function f_EPTF_RBTreeI_destroyIntegerNode(inout EPTF_Integer_RedBlackTree pl_tree, in integer pl_z) { |
| f_EPTF_RBTree_destroyNode(pl_tree.nodes, pl_tree.freeHead, pl_tree.freeTail, pl_z); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_RBTreeI_invalidateIntegerNode |
| // |
| // Purpose: |
| // sets node of the given index (pl_z) invalid |
| // |
| // Parameters: |
| // pl_tree - *inout* <EPTF_Integer_RedBlackTree> - the up-to-date integer red-black-tree itself |
| // pl_z - *in* *integer* - index of the integer tree node to invalidate |
| // |
| // Return Value: |
| // (none) |
| /////////////////////////////////////////////////////////// |
| |
| friend function f_EPTF_RBTreeI_invalidateIntegerNode(inout EPTF_Integer_RedBlackTree pl_tree, in integer pl_z) { |
| f_EPTF_RBTree_invalidateNode(pl_tree.nodes, pl_z); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_RBTreeI_getSmallestIntegerElementIndexFromCache |
| // |
| // Purpose: |
| // Gets smallest keyed integer node index from cache. |
| // Refreshes cache if invalid. |
| // |
| // Parameters: |
| // pl_tree - *inout* <EPTF_Integer_RedBlackTree> - the up-to-date integer red-black-tree itself |
| // pl_idx - *inout* *integer* - smallest key index |
| // |
| // Return Value: |
| // boolean - success |
| /////////////////////////////////////////////////////////// |
| |
| friend function f_EPTF_RBTreeI_getSmallestIntegerElementIndexFromCache(in EPTF_Integer_RedBlackTree pl_tree, inout integer pl_idx) return boolean { |
| var integer root := pl_tree.nodes[pl_tree.root].left; |
| |
| var boolean vl_result := false; |
| if (root == pl_tree.nil) { |
| // The tree is empty. |
| pl_idx := -1; |
| return false; |
| } |
| |
| // If the cache is valid... |
| if (pl_tree.isSmallestCacheValid) { |
| pl_idx := pl_tree.smallestKeyIndex; |
| vl_result := true; |
| } else { |
| // We have to search and refresh the cache |
| pl_idx := f_EPTF_RBTreeI_searchSmallestNodeIndex(pl_tree); |
| vl_result := true; |
| } |
| return vl_result; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_RBTreeI_searchSmallestNodeIndex |
| // |
| // Purpose: |
| // Searches for smallest key node in integer tree. |
| // Also refreshes smallest key cache if found. |
| // |
| // Parameters: |
| // pl_tree - *inout* <EPTF_Integer_RedBlackTree> - the up-to-date integer red-black-tree |
| // |
| // Return Value: |
| // integer - smallest key index. |
| // Returns -1 if the tree is empty. |
| /////////////////////////////////////////////////////////// |
| |
| friend function f_EPTF_RBTreeI_searchSmallestNodeIndex(in EPTF_Integer_RedBlackTree pl_tree) return integer { |
| |
| var integer nil := pl_tree.nil; |
| var integer root := pl_tree.nodes[pl_tree.root].left; |
| |
| |
| if (root == nil) { |
| // Tree is empty... EXIT |
| return -1; |
| } |
| |
| var integer x := root; |
| while (pl_tree.nodes[x].left != nil) { |
| x := pl_tree.nodes[x].left; |
| } // while |
| |
| //pl_tree.smallestKeyIndex := x; |
| //pl_tree.isSmallestCacheValid := true; |
| |
| return x; |
| |
| /* Previous solution. The new (above) might be faster: has less if operation. |
| var integer vl_x := pl_tree.root.left; |
| while (vl_x != nil and not vl_isFound) { |
| if (pl_tree.nodes[vl_x].left == nil) { |
| // no more left child -> end of the tree |
| // refreshing cache |
| pl_tree.smallestKeyIndex := vl_x; |
| pl_tree.isSmallestCacheValid := true; |
| vl_isFound := true; |
| } else { |
| // go forward to left |
| vl_x := pl_tree.nodes[vl_x].left; |
| } |
| } // while |
| |
| return vl_x; |
| |
| */ |
| |
| |
| |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_RBTreeI_checkMaxSize |
| // |
| // Purpose: |
| // Function to check if the size of the tree exceeds a certain limit. |
| // |
| // Parameters: |
| // pl_caller - *in* *charstring* - caller function, use %definitionId when calling |
| // pl_tree - *inout* <EPTF_Integer_RedBlackTree> - the tree in question |
| // |
| // Return Value: |
| // - |
| // |
| // Detailed Comments: |
| // The tree MUST be initialized by calling f_EPTF_RBTreeI_initIntegerTree. |
| // |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_RBTreeI_checkMaxSize(in charstring pl_caller, inout EPTF_Integer_RedBlackTree pl_tree) |
| { |
| if(c_EPTF_Common_debugSwitch and pl_tree.acceptableMaxSize >= 0) { |
| if(pl_tree.nOfElements > pl_tree.acceptableMaxSize) { |
| //EPTF_Logging_debug |
| f_EPTF_Common_warning(log2str(pl_caller, ": tree exceeds acceptable max size of ", pl_tree.acceptableMaxSize, " elements.")); |
| f_EPTF_Common_warning(log2str(pl_caller, ": increasing acceptable max size by a factor of ", tsp_CLL_debug_increasePercentage4AcceptableMaxSize)); |
| pl_tree.acceptableMaxSize := float2int(int2float(pl_tree.acceptableMaxSize) |
| * (1.0+tsp_CLL_debug_increasePercentage4AcceptableMaxSize)); |
| f_EPTF_Common_warning(log2str(pl_caller, ": new acceptable max size: ", pl_tree.acceptableMaxSize)); |
| } |
| } |
| } |
| |
| } //module |