Nut/OS  4.10.3
API Reference
lpushpop.c
Go to the documentation of this file.
00001 /*
00002  * Copyright 2010 by egnite GmbH
00003  *
00004  * All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  *
00010  * 1. Redistributions of source code must retain the above copyright
00011  *    notice, this list of conditions and the following disclaimer.
00012  * 2. Redistributions in binary form must reproduce the above copyright
00013  *    notice, this list of conditions and the following disclaimer in the
00014  *    documentation and/or other materials provided with the distribution.
00015  * 3. Neither the name of the copyright holders nor the names of
00016  *    contributors may be used to endorse or promote products derived
00017  *    from this software without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00020  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00021  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00022  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00023  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00024  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00025  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00026  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00027  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00028  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00029  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00030  * SUCH DAMAGE.
00031  *
00032  * For additional information see http://www.ethernut.de/
00033  */
00034 
00035 /*
00036  * \file gorp/list/lpushpop.c
00037  * \brief Linked list push and pop functions.
00038  *
00039  * \verbatim
00040  * $Id$
00041  * \endverbatim
00042  */
00043 
00044 #include <sys/nutdebug.h>
00045 
00046 #include <gorp/lili.h>
00047 
00052 
00066 LILI_NODE *LiLiLocateItem(LILI *list, LILI_ITEMREF ref)
00067 {
00068     LILI_NODE *node;
00069 
00070     /* Sanity checks. */
00071     NUTASSERT(list != NULL);
00072 
00073     for (node = LiLiFirstNode(list); node; node = LiLiNextNode(node)) {
00074         if (list->lst_icompare(LiLiNodeItem(node), ref) >= 0) {
00075             break;
00076         }
00077     }
00078     return node;
00079 }
00080 
00093 LILI_NODE *LiLiFindItem(LILI *list, LILI_ITEMREF ref)
00094 {
00095     LILI_NODE *node;
00096     int rc;
00097 
00098     /* Sanity checks. */
00099     NUTASSERT(list != NULL);
00100 
00101     for (node = LiLiFirstNode(list); node; node = LiLiNextNode(node)) {
00102         rc = list->lst_icompare(LiLiNodeItem(node), ref);
00103         if (rc == 0) {
00104             break;
00105         }
00106         if (rc > 0 && LiLiIsSorted(list)) {
00107             return NULL;
00108         }
00109     }
00110     return node;
00111 }
00112 
00137 int LiLiPushItem(LILI *list, LILI_ITEMREF ref)
00138 {
00139     LILI_NODE *node;
00140     int rc;
00141 
00142     /* Sanity checks. */
00143     NUTASSERT(list != NULL);
00144 
00145     node = LiLiLastNode(list);
00146     if (node) {
00147         if (LiLiIsSorted(list)) {
00148             /* A sorted list, compare the new with the last item. */
00149             rc = list->lst_icompare(LiLiNodeItem(node), ref);
00150             if (rc <= 0) {
00151                 /* The new item is greater or equal, so we should append 
00152                 ** it. But only, if either the items are not equal or if
00153                 ** this is not a list of unique items only. */
00154                 if (rc || !LiLiHasUniqueItems(list)) {
00155                     rc = LiLiInsertItemAfterNode(list, node, ref) ? 0 : -1;
00156                 }
00157                 return rc;
00158             }
00159             /* The new item is lower than the last one in the list. Search
00160             ** the first node with an item greater or equal than the new one. */
00161             node = LiLiLocateItem(list, ref);
00162             /* If the list has unique items only, then ignore an equal item. */
00163             if (LiLiHasUniqueItems(list) && list->lst_icompare(LiLiNodeItem(node), ref) == 0) {
00164                 return 0;
00165             }
00166         } else {
00167             /* Do not insert an equal item into a unique list. */
00168             if (LiLiHasUniqueItems(list) && LiLiFindItem(list, ref)) {
00169                 return 0;
00170             }
00171             /* If not a sorted list, add new items in front. */
00172             node = LiLiFirstNode(list);
00173         }
00174     }
00175     /* Add a new node. */
00176     return LiLiInsertItemBeforeNode(list, node, ref) ? 0 : -1;
00177 }
00178 
00191 int LiLiPopItem(LILI *list, LILI_ITEMREF *refp)
00192 {
00193     LILI_NODE *node;
00194 
00195     /* Sanity checks. */
00196     NUTASSERT(list != NULL);
00197 
00198     /* Get the first node, check if the list is empty. */
00199     node = LiLiFirstNode(list);
00200     if (node) {
00201         /* List is not empty. However, if this is a FIFO queue, remove 
00202         ** the last node instead. */
00203         if (LiLiIsFifo(list)) {
00204             node = LiLiLastNode(list);
00205         }
00206         /* Pass the item reference to the caller and remove the node. */
00207         *refp = LiLiNodeItem(node);
00208         LiLiRemoveNode(list, node);
00209     }
00210     return node ? 0 : -1;
00211 }
00212