Example #1
0
/*-
 *-----------------------------------------------------------------------
 * Lst_Concat --
 *	Concatenate two lists. New elements are created to hold the data
 *	elements but the elements themselves are not copied.
 *	If the elements themselves should be duplicated to avoid
 *	confusion with another list, the Lst_Duplicate function
 *	should be called first.
 *
 * Side Effects:
 *	New elements are created and appended to the first list.
 *-----------------------------------------------------------------------
 */
void
Lst_Concat(Lst l1, Lst l2)
{
	LstNode ln;	/* original LstNode */
	LstNode nln;	/* new LstNode */
	LstNode last;	/* the last element in the list. Keeps
			 * bookkeeping until the end */
	if (l2->firstPtr != NULL) {
		/* The loop simply goes through the entire second list creating
		 * new LstNodes and filling in the nextPtr, and prevPtr to fit
		 * into l1 and its datum field from the datum field of the
		 * corresponding element in l2. The 'last' node follows the
		 * last of the new nodes along until the entire l2 has been
		 * appended.  Only then does the bookkeeping catch up with the
		 * changes. During the first iteration of the loop, if 'last'
		 * is NULL, the first list must have been empty so the
		 * newly-created node is made the first node of the list.  */
		for (last = l1->lastPtr, ln = l2->firstPtr; ln != NULL;
		     ln = ln->nextPtr) {
			PAlloc(nln, LstNode);
			nln->datum = ln->datum;
			if (last != NULL)
				last->nextPtr = nln;
			else
				l1->firstPtr = nln;
			nln->prevPtr = last;
			last = nln;
		}

		/* Finish bookkeeping. The last new element becomes the last
		 * element of l1.  */
		l1->lastPtr = last;
		last->nextPtr = NULL;
	}
}
Example #2
0
/*-
 *-----------------------------------------------------------------------
 * Lst_Append --
 *	Create a new node and add it to the given list after the given node.
 *
 * Side Effects:
 *	A new ListNode is created and linked in to the List. The lastPtr
 *	field of the List will be altered if ln is the last node in the
 *	list. lastPtr and firstPtr will alter if the list was empty and
 *	ln was NULL.
 *
 *-----------------------------------------------------------------------
 */
void
Lst_Append(Lst l, LstNode after, void *d)
{
	LstNode	nLNode;

	if (after == NULL && !Lst_IsEmpty(l))
		return;

	if (after != NULL && Lst_IsEmpty(l))
		return;

	PAlloc(nLNode, LstNode);
	nLNode->datum = d;

	if (after == NULL) {
		nLNode->nextPtr = nLNode->prevPtr = NULL;
		l->firstPtr = l->lastPtr = nLNode;
	} else {
		nLNode->prevPtr = after;
		nLNode->nextPtr = after->nextPtr;

		after->nextPtr = nLNode;
		if (nLNode->nextPtr != NULL)
			nLNode->nextPtr->prevPtr = nLNode;

		if (after == l->lastPtr)
			l->lastPtr = nLNode;
	}
}
Example #3
0
/*-
 *-----------------------------------------------------------------------
 * Lst_Insert --
 *	Insert a new node with the given piece of data before the given
 *	node in the given list.
 *
 * Side Effects:
 *	the firstPtr field will be changed if ln is the first node in the
 *	list.
 *
 *-----------------------------------------------------------------------
 */
void
Lst_Insert(Lst l, LstNode before, void *d)
{
	LstNode nLNode;


	if (before == NULL && !Lst_IsEmpty(l))
		return;

	if (before != NULL && Lst_IsEmpty(l))
		return;

	PAlloc(nLNode, LstNode);

	nLNode->datum = d;

	if (before == NULL) {
		nLNode->prevPtr = nLNode->nextPtr = NULL;
		l->firstPtr = l->lastPtr = nLNode;
	} else {
		nLNode->prevPtr = before->prevPtr;
		nLNode->nextPtr = before;

		if (nLNode->prevPtr != NULL)
			nLNode->prevPtr->nextPtr = nLNode;
		before->prevPtr = nLNode;

		if (before == l->firstPtr)
			l->firstPtr = nLNode;
	}
}
Example #4
0
/*-
 *-----------------------------------------------------------------------
 * Lst_Init --
 *	Create and initialize a new list.
 *
 * Input:
 *	circ		TRUE if the list should be made circular
 *
 * Results:
 *	The created list.
 *
 * Side Effects:
 *	A list is created, what else?
 *
 *-----------------------------------------------------------------------
 */
Lst
Lst_Init(Boolean circ)
{
    List	nList;

    PAlloc (nList, List);

    nList->firstPtr = NULL;
    nList->lastPtr = NULL;
    nList->isOpen = FALSE;
    nList->isCirc = circ;
    nList->atEnd = Unknown;

    return (nList);
}
Example #5
0
void
Lst_AtEnd(Lst l, void *d)
{
	LstNode	ln;

	PAlloc(ln, LstNode);
	ln->datum = d;

	ln->prevPtr = l->lastPtr;
	ln->nextPtr = NULL;
	if (l->lastPtr == NULL)
		l->firstPtr = ln;
	else
		l->lastPtr->nextPtr = ln;
	l->lastPtr = ln;
}
Example #6
0
/*-
 *-----------------------------------------------------------------------
 * Lst_InsertBefore --
 *	Insert a new node with the given piece of data before the given
 *	node in the given list.
 *
 * Input:
 *	l		list to manipulate
 *	ln		node before which to insert d
 *	d		datum to be inserted
 *
 * Results:
 *	SUCCESS or FAILURE.
 *
 * Side Effects:
 *	the firstPtr field will be changed if ln is the first node in the
 *	list.
 *
 *-----------------------------------------------------------------------
 */
ReturnStatus
Lst_InsertBefore(Lst l, LstNode ln, void *d)
{
    ListNode	nLNode;	/* new lnode for d */
    ListNode	lNode = ln;
    List 	list = l;


    /*
     * check validity of arguments
     */
    if (LstValid (l) && (LstIsEmpty (l) && ln == NULL))
	goto ok;

    if (!LstValid (l) || LstIsEmpty (l) || !LstNodeValid (ln, l)) {
	return (FAILURE);
    }

    ok:
    PAlloc (nLNode, ListNode);

    nLNode->datum = d;
    nLNode->useCount = nLNode->flags = 0;

    if (ln == NULL) {
	if (list->isCirc) {
	    nLNode->prevPtr = nLNode->nextPtr = nLNode;
	} else {
	    nLNode->prevPtr = nLNode->nextPtr = NULL;
	}
	list->firstPtr = list->lastPtr = nLNode;
    } else {
	nLNode->prevPtr = lNode->prevPtr;
	nLNode->nextPtr = lNode;

	if (nLNode->prevPtr != NULL) {
	    nLNode->prevPtr->nextPtr = nLNode;
	}
	lNode->prevPtr = nLNode;

	if (lNode == list->firstPtr) {
	    list->firstPtr = nLNode;
	}
    }

    return (SUCCESS);
}
Example #7
0
/*-
 *-----------------------------------------------------------------------
 * Lst_InsertAfter --
 *	Create a new node and add it to the given list after the given node.
 *
 * Input:
 *	l		affected list
 *	ln		node after which to append the datum
 *	d		said datum
 *
 * Results:
 *	SUCCESS if all went well.
 *
 * Side Effects:
 *	A new ListNode is created and linked in to the List. The lastPtr
 *	field of the List will be altered if ln is the last node in the
 *	list. lastPtr and firstPtr will alter if the list was empty and
 *	ln was NILLNODE.
 *
 *-----------------------------------------------------------------------
 */
ReturnStatus
Lst_InsertAfter(Lst l, LstNode ln, ClientData d)
{
    List 	list;
    ListNode	lNode;
    ListNode	nLNode;

    if (LstValid (l) && (ln == NILLNODE && LstIsEmpty (l))) {
	goto ok;
    }

    if (!LstValid (l) || LstIsEmpty (l)  || ! LstNodeValid (ln, l)) {
	return (FAILURE);
    }
    ok:

    list = l;
    lNode = ln;

    PAlloc (nLNode, ListNode);
    nLNode->datum = d;
    nLNode->useCount = nLNode->flags = 0;

    if (lNode == NilListNode) {
	if (list->isCirc) {
	    nLNode->nextPtr = nLNode->prevPtr = nLNode;
	} else {
	    nLNode->nextPtr = nLNode->prevPtr = NilListNode;
	}
	list->firstPtr = list->lastPtr = nLNode;
    } else {
	nLNode->prevPtr = lNode;
	nLNode->nextPtr = lNode->nextPtr;

	lNode->nextPtr = nLNode;
	if (nLNode->nextPtr != NilListNode) {
	    nLNode->nextPtr->prevPtr = nLNode;
	}

	if (lNode == list->lastPtr) {
	    list->lastPtr = nLNode;
	}
    }

    return (SUCCESS);
}
Example #8
0
/*-
 *-----------------------------------------------------------------------
 * Lst_Concat --
 *	Concatenate two lists. New elements are created to hold the data
 *	elements, if specified, but the elements themselves are not copied.
 *	If the elements should be duplicated to avoid confusion with another
 *	list, the Lst_Duplicate function should be called first.
 *	If LST_CONCLINK is specified, the second list is destroyed since
 *	its pointers have been corrupted and the list is no longer useable.
 *
 * Input:
 *	l1		The list to which l2 is to be appended
 *	l2		The list to append to l1
 *	flags		LST_CONCNEW if LstNode's should be duplicated
 *			LST_CONCLINK if should just be relinked
 *
 * Results:
 *	SUCCESS if all went well. FAILURE otherwise.
 *
 * Side Effects:
 *	New elements are created and appended the first list.
 *-----------------------------------------------------------------------
 */
ReturnStatus
Lst_Concat(Lst l1, Lst l2, int flags)
{
    ListNode  	ln;     /* original LstNode */
    ListNode  	nln;    /* new LstNode */
    ListNode  	last;   /* the last element in the list. Keeps
				 * bookkeeping until the end */
    List 	list1 = l1;
    List 	list2 = l2;

    if (!LstValid (l1) || !LstValid (l2)) {
	return (FAILURE);
    }

    if (flags == LST_CONCLINK) {
	if (list2->firstPtr != NULL) {
	    /*
	     * We set the nextPtr of the
	     * last element of list two to be NIL to make the loop easier and
	     * so we don't need an extra case should the first list turn
	     * out to be non-circular -- the final element will already point
	     * to NIL space and the first element will be untouched if it
	     * existed before and will also point to NIL space if it didn't.
	     */
	    list2->lastPtr->nextPtr = NULL;
	    /*
	     * So long as the second list isn't empty, we just link the
	     * first element of the second list to the last element of the
	     * first list. If the first list isn't empty, we then link the
	     * last element of the list to the first element of the second list
	     * The last element of the second list, if it exists, then becomes
	     * the last element of the first list.
	     */
	    list2->firstPtr->prevPtr = list1->lastPtr;
	    if (list1->lastPtr != NULL) {
 		list1->lastPtr->nextPtr = list2->firstPtr;
	    } else {
		list1->firstPtr = list2->firstPtr;
	    }
	    list1->lastPtr = list2->lastPtr;
	}
	if (list1->isCirc && list1->firstPtr != NULL) {
	    /*
	     * If the first list is supposed to be circular and it is (now)
	     * non-empty, we must make sure it's circular by linking the
	     * first element to the last and vice versa
	     */
	    list1->firstPtr->prevPtr = list1->lastPtr;
	    list1->lastPtr->nextPtr = list1->firstPtr;
	}
	free(l2);
    } else if (list2->firstPtr != NULL) {
	/*
	 * We set the nextPtr of the last element of list 2 to be nil to make
	 * the loop less difficult. The loop simply goes through the entire
	 * second list creating new LstNodes and filling in the nextPtr, and
	 * prevPtr to fit into l1 and its datum field from the
	 * datum field of the corresponding element in l2. The 'last' node
	 * follows the last of the new nodes along until the entire l2 has
	 * been appended. Only then does the bookkeeping catch up with the
	 * changes. During the first iteration of the loop, if 'last' is nil,
	 * the first list must have been empty so the newly-created node is
	 * made the first node of the list.
	 */
	list2->lastPtr->nextPtr = NULL;
	for (last = list1->lastPtr, ln = list2->firstPtr;
	     ln != NULL;
	     ln = ln->nextPtr)
	{
	    PAlloc (nln, ListNode);
	    nln->datum = ln->datum;
	    if (last != NULL) {
		last->nextPtr = nln;
	    } else {
		list1->firstPtr = nln;
	    }
	    nln->prevPtr = last;
	    nln->flags = nln->useCount = 0;
	    last = nln;
	}

	/*
	 * Finish bookkeeping. The last new element becomes the last element
	 * of list one.
	 */
	list1->lastPtr = last;

	/*
	 * The circularity of both list one and list two must be corrected
	 * for -- list one because of the new nodes added to it; list two
	 * because of the alteration of list2->lastPtr's nextPtr to ease the
	 * above for loop.
	 */
	if (list1->isCirc) {
	    list1->lastPtr->nextPtr = list1->firstPtr;
	    list1->firstPtr->prevPtr = list1->lastPtr;
	} else {
	    last->nextPtr = NULL;
	}

	if (list2->isCirc) {
	    list2->lastPtr->nextPtr = list2->firstPtr;
	}
    }

    return (SUCCESS);
}