FUNCTION obj_list::init ; Set the size of the obj_list to 0. Nothing else to do. self.size = 0 RETURN, 1 END ; ------------------------------------------------------------------------------------------------ PRO obj_list::cleanup ; Just call the clear method to delete all the nodes. self->clear ; Were done! RETURN END ; ------------------------------------------------------------------------------------------------ PRO obj_list::clear ; If the obj_list is empty, then just return. IF self.size EQ 0 THEN RETURN ; Kludge ))))))))))))))))))))))))))))))))))))))))))))))))))))))) IF NOT OBJ_VALID (self.first) THEN RETURN ; Kludge ))))))))))))))))))))))))))))))))))))))))))))))))))))))) ; Set obj to point to the first node on the obj_list. obj = self.first ; Loop to move through the entire obj_list, deleting each node as it is encountered. WHILE obj NE self.null DO BEGIN ; Set tmp to point to subsequent node in the obj_list. tmp = obj.next ; Destroy the node object. OBJ_DESTROY, obj ; Move ptr to point to the next node in the obj_list (pointed to by tmp). obj = tmp ENDWHILE ; Reset size to 0. self.size = 0 ; Reset the first and last pointers. self.first = self.null self.last = self.null ; All done. RETURN END ; ------------------------------------------------------------------------------------------------ PRO obj_list::add, node ; Make sure that node exists. If node does not exist, then simply return (silent error). IF N_ELEMENTS (node) EQ 0 THEN RETURN ; Make sure that node is an object. If node is not an object, then simply return. ; (silent error) IF self->get_type (node) NE 11 THEN RETURN ; Make sure that node inherits BASE_NODE_OBJ. If node does not inherit this object then ; simply return (silent error). IF NOT OBJ_ISA (node, 'BASE_NODE_OBJ') THEN RETURN ; Check if there are any items on the obj_list. ; If it is empty then we have to begin the list from scratch. IF self.size EQ 0 THEN BEGIN ; Empty obj_list. The node that was passed to us as a parameter will be the first and ; only node on the obj_list. node.next = self.null node.prev = self.null self.first = node self.last = node ENDIF ELSE BEGIN ; Ok, there are already some nodes. First check to make sure we are not adding ; a named node to the obj_list with the same name as a node already on the obj_list. ; If we are then just return. IF self->search (node.name) THEN RETURN ; Now decide if need insert the new node at the begining, in the middle or at the end of the ; obj_list. We will first check for an insertion at the start or end of the list. ; Set the flags for first, middle and last to 0 (FALSE). first = 0 last = 0 middle = 0 ; Check for insertion at the begining of the obj_list. IF node.name LT self.first->get_name () THEN first = 1 ; Check for insertion at the end of the obj_list. IF node.name GT self.last->get_name () THEN last = 1 ; Check if neither first nor last is set. If neither is, then we have to insert our ; node in the middle of the obj_list. IF NOT first AND NOT last THEN BEGIN ; Set the flag middle. middle = 1 ; Now search through the obj_list looking for the correct place to add new node. ; Begin by setting loc to point to the first node on the obj_list. Also set found ; to 0, this will cause the loop to exit when the correct location to insert ; the node has been found. loc = self.first found = 0 ; Loop to move through the entire obj_list, checking each node to make sure that it is ; located prior to name according to the ascii collating sequence. WHILE NOT found AND loc NE self.null DO BEGIN ; Check if the node should lexically come before the node pointed to by loc IF node.name LT loc.name THEN BEGIN ; OK, found where to insert the node. Move loc back one node. loc = loc.prev ; Set found to 1 and get out of the loop. found = 1 ENDIF ELSE BEGIN ; Otherwise, move loc to point to the next node on the list. loc = loc.next ENDELSE ENDWHILE ENDIF ; Check where we should insert the the new node (according to which flag is set -- ; first, last or middle) and then insert the node in the proper place. IF first THEN BEGIN ; Insert the node at the begining of the obj_list. ; ; Set up the pointers in the new node. node.next = self.first node.prev = self.null ; Insert the new node at the beginning of the list. self.first->set_prev, node self.first = node ENDIF IF last THEN BEGIN ; Insert the node at the end of the obj_list. ; Set up the pointers in the new node. node.next = self.null node.prev = self.last ; Insert the new node at the end of the list. self.last->set_next, node self.last = node ENDIF IF middle THEN BEGIN ; Insert the node in the middle of the obj_list. ; Set up the pointers in the new node. node.next = loc.next node.prev = loc ; Insert the new node into the list. loc.next->set_prev, node loc.next = node ENDIF ENDELSE ; Increment the size counter of the list. self.size = self.size + 1 ; Were done! returning... RETURN END ; ------------------------------------------------------------------------------------------------ FUNCTION obj_list::list, EMPTY = empty ; First, check if the obj_list is empty. If it is then we will just return -1. IF self.size EQ 0 THEN BEGIN IF N_ELEMENTS (empty) NE 0 THEN empty = 1 return, -1 ENDIF ; Create a string array to hold the name of each node in the obj_list. list = STRARR (self.size) ; Now loop through the entire structure and get the all the name strings. ; Set ptr to point to the first node on the obj_list. ; Use cnt to keep count of which node we are accessing. ptr = self.first cnt = 0 ; Loop to move through the entire obj_list, copy in the name of each node into the ; array list. WHILE ptr NE self.null DO BEGIN ; Copy the string from the node into the array list. list [cnt] = ptr.name ; Move ptr to point to the next node in the obj_list. ptr = ptr.next ; Increment cnt by 1. cnt = cnt + 1 ENDWHILE ; Make sure that empty is set to FALSE (if it exists). IF N_ELEMENTS (empty) NE 0 THEN empty = 0 ; Return the list of values we just extracted. RETURN, list END ; ------------------------------------------------------------------------------------------------ FUNCTION obj_list::search, val ; If the obj_list is empty, then just return 0 (FALSE). IF self.size EQ 0 THEN RETURN, 0 ; Force val to be a string. In the process, remove leading and trailing blanks. str = STRTRIM (STRING (val), 1) ; Now we need to search through the obj_list looking for the requested string. ; Begin by seting obj to point to the first node on the obj_list. obj = self.first ; Loop to move through the entire obj_list, checking each node to see if its name tag is set to ; the requested string. The loop ends when all nodes have been searched. Finding a node ; with a name tag that would occur prior to the search sting using the the ASCII collating ; sequence or finding the node that is the target of the search will cause the function ; to immediately return a result. WHILE obj NE self.null DO BEGIN ; Check if search target is contained within the current node. ; If it is then we are done. IF str EQ obj.name THEN RETURN, 1 ; Check if str should lexically come before the node pointed to by ptr. If it does, ; then the target is not in the obj_list and there is no point in continueing the search. IF str LT obj.name THEN RETURN, 0 ; Otherwise, move pointer to point to the next node on the list. obj = obj.next ENDWHILE ; Oops. The search failed. Return 0. RETURN, 0 END ; ------------------------------------------------------------------------------------------------ FUNCTION obj_list::get, val ; If the obj_list is empty, then just return 0 (FALSE). IF self.size EQ 0 THEN RETURN, 0 ; Force val to be a string. In the process, remove leading and trailing blanks. str = STRTRIM (STRING (val), 1) ; Now we need to search through the obj_list looking for the requested string. ; Begin by seting ptr to point to the first node on the obj_list. ptr = self.first ; Loop to move through the entire obj_list, checking to see if the name of each node is set to ; the requested string. The loop ends when all nodes have been searched. Finding a node ; with a name that would occur prior to the search sting using the the ASCII collating ; sequence or finding the node that is the target of the search will cause the function ; to immediately return a result. WHILE ptr NE self.null DO BEGIN ; Check if search target is contained within the current node. ; If it is then return a reference to that node. IF str EQ ptr.name THEN RETURN, ptr ; Check if str should lexically come before the node pointed to by ptr. If it does, ; then the target is not in the obj_list and there is no point in continueing the search. IF str LT ptr.name THEN RETURN, self.null ; Otherwise, move pointer to point to the next node on the list. ptr = ptr.next ENDWHILE ; Oops. The search failed. Return a referance to a NULL object. RETURN, self.null END ; ------------------------------------------------------------------------------------------------ FUNCTION obj_list::unlink, val ; If the obj_list is empty, then just return a NULL. IF self.size EQ 0 THEN RETURN, self.null ; Make sure that val exists. If val does not exist, then return a NULL IF N_ELEMENTS (val) EQ 0 THEN RETURN, self.null ; Force val to be a string. In the process, remove leading and trailing blanks. str = STRTRIM (STRING (val), 1) ; Now we need to search through the obj_list looking for the requested string. ; Begin by seting ptr to point to the first node on the obj_list. ptr = self.first ; Loop to move through the entire obj_list, checking to see if the name of each node is set to ; the requested string. The loop ends when all nodes have been searched. Finding a node ; with a name that would occur prior to the search sting using the ASCII collating ; sequence or finding the node that is the target of the search will cause the function ; to immediately return a result. WHILE ptr NE self.null DO BEGIN ; Check if search target is contained within the current node. ; If it is then we have to remove it. IF str EQ ptr.name THEN BEGIN ; Unlink the node from the obj_list. How we handle this task depends on the position ; of the node within the obj_list. Special cases are the node is the first node on the ; list, the last node on the list or there is only one node on the list. The nominal ; case is that the node is in the middle of the list. After unlinking the node, we ; will then do an unconditional jump to the part of the routine that cleans up the ; the node and returns a pointer to it. IF self.size EQ 1 THEN BEGIN ; The obj_list consist of a single node. ; Unlink the requested node from the the obj_list. self.first = self.null self.last = self.null ; Jump to the final cleanup and return a pointer to the node. GOTO, CLEANUP ENDIF IF ptr EQ self.first THEN BEGIN ; The node is the first node on the list. ; Unlink the requested node from the the obj_list. self.first = ptr.next self.first->set_prev ; Jump to the final cleanup and return a pointer to the node. GOTO, CLEANUP ENDIF IF ptr EQ self.last THEN BEGIN ; The node is the last node on the list. ; Unlink the requested node from the the obj_list. self.last = ptr.prev self.last->set_next ; Jump to the final cleanup and return a pointer to the node. GOTO, CLEANUP ENDIF ; Nominal Case The node is in the middle of the list. ; Unlink the requested node from the the obj_list. ptr.next->set_prev, ptr.prev ptr.prev->set_next, ptr.next ; Do the final cleanup and return a pointer to the node. CLEANUP: ; Set the next and prev pointers in the node to NULL. ptr.prev = self.null ptr.next = self.null ; Decreement the count of the number of nodes on the obj_list by 1 self.size = self.size - 1 ; Return the pointer to the node we just unlinked. RETURN, ptr ENDIF ; Check if str should lexically come before the node pointed to by ptr. If it does, ; then the target is not in the obj_list and there is no point in continueing the search. IF str LT ptr.name THEN RETURN, self.null ; Otherwise, move pointer to point to the next node on the list. ptr = ptr.next ENDWHILE ; Oops. The search failed. Return a NULL. RETURN, self.null END ; ------------------------------------------------------------------------------------------------ FUNCTION obj_list::size ; Return the number of node in the obj_list. RETURN, self.size END ; ------------------------------------------------------------------------------------------------ PRO obj_list__define struct = {OBJ_LIST, $ ; Name of the object structure. first: OBJ_NEW (), $ ; Pointer to first node on the obj_list. last: OBJ_NEW (), $ ; Pointer to last node on the obj_list. null: OBJ_NEW (), $ ; NULL pointer definition size: 0, $ ; Number of nodes in the obj_list. INHERITS olib $ ; object library } END