0N/A/*
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A/* $XConsortium: list.c /main/4 1996/10/14 15:03:56 swick $ */
0N/A/** ------------------------------------------------------------------------
0N/A This file contains routines for manipulating generic lists.
0N/A Lists are implemented with a "harness". In other words, each
0N/A node in the list consists of two pointers, one to the data item
0N/A and one to the next node in the list. The head of the list is
0N/A the same struct as each node, but the "item" ptr is used to point
0N/A to the current member of the list (used by the first_in_list and
0N/A next_in_list functions).
0N/A
0N/A This file is available under and governed by the GNU General Public
0N/A License version 2 only, as published by the Free Software Foundation.
0N/A However, the following notice accompanied the original version of this
0N/A file:
0N/A
0N/ACopyright (c) 1994 Hewlett-Packard Co.
0N/ACopyright (c) 1996 X Consortium
0N/A
0N/APermission is hereby granted, free of charge, to any person obtaining
0N/Aa copy of this software and associated documentation files (the
0N/A"Software"), to deal in the Software without restriction, including
0N/Awithout limitation the rights to use, copy, modify, merge, publish,
0N/Adistribute, sublicense, and sell copies of the Software, and to
0N/Apermit persons to whom the Software is furnished to do so, subject to
0N/Athe following conditions:
0N/A
0N/AThe above copyright notice and this permission notice shall be included
0N/Ain all copies or substantial portions of the Software.
0N/A
0N/ATHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
0N/AOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
0N/AMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
0N/AIN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
0N/AOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0N/AARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0N/AOTHER DEALINGS IN THE SOFTWARE.
0N/A
0N/AExcept as contained in this notice, the name of the X Consortium shall
0N/Anot be used in advertising or otherwise to promote the sale, use or
0N/Aother dealings in this Software without prior written authorization
0N/Afrom the X Consortium.
0N/A
0N/A ----------------------------------------------------------------------- **/
0N/A
0N/A#include <stdio.h>
4632N/A#include <stdlib.h>
0N/A#include "list.h"
0N/A
0N/A
0N/A/** ------------------------------------------------------------------------
0N/A Sets the pointers of the specified list to NULL.
0N/A --------------------------------------------------------------------- **/
0N/A#if NeedFunctionPrototypes
0N/Avoid zero_list(list_ptr lp)
0N/A#else
0N/Avoid zero_list(lp)
0N/A list_ptr lp;
0N/A#endif
0N/A{
0N/A lp->next = NULL;
0N/A lp->ptr.item = NULL;
0N/A}
0N/A
0N/A
0N/A/** ------------------------------------------------------------------------
0N/A Adds item to the list pointed to by lp. Finds the end of the
0N/A list, then mallocs a new list node onto the end of the list.
0N/A The item pointer in the new node is set to "item" passed in,
0N/A and the next pointer in the new node is set to NULL.
0N/A Returns 1 if successful, 0 if the malloc failed.
0N/A -------------------------------------------------------------------- **/
0N/A#if NeedFunctionPrototypes
0N/Aint32_t add_to_list(list_ptr lp, void *item)
0N/A#else
0N/Aint32_t add_to_list(lp, item)
0N/A list_ptr lp;
0N/A void *item;
0N/A#endif
0N/A{
0N/A while (lp->next) {
0N/A lp = lp->next;
0N/A }
0N/A if ((lp->next = (list_ptr) malloc( sizeof( list_item))) == NULL) {
0N/A
0N/A return 0;
0N/A }
0N/A lp->next->ptr.item = item;
0N/A lp->next->next = NULL;
0N/A
0N/A return 1;
0N/A}
0N/A
0N/A
0N/A/** ------------------------------------------------------------------------
0N/A Creates a new list and sets its pointers to NULL.
0N/A Returns a pointer to the new list.
0N/A -------------------------------------------------------------------- **/
0N/Alist_ptr new_list ()
0N/A{
0N/A list_ptr lp;
0N/A
0N/A if (lp = (list_ptr) malloc( sizeof( list_item))) {
0N/A lp->next = NULL;
0N/A lp->ptr.item = NULL;
0N/A }
0N/A
0N/A return lp;
0N/A}
0N/A
0N/A
0N/A/** ------------------------------------------------------------------------
0N/A Creates a new list head, pointing to the same list as the one
0N/A passed in. If start_at_curr is TRUE, the new list's first item
0N/A is the "current" item (as set by calls to first/next_in_list()).
0N/A If start_at_curr is FALSE, the first item in the new list is the
0N/A same as the first item in the old list. In either case, the
0N/A curr pointer in the new list is the same as in the old list.
0N/A Returns a pointer to the new list head.
0N/A -------------------------------------------------------------------- **/
0N/A#if NeedFunctionPrototypes
0N/Alist_ptr dup_list_head(list_ptr lp, int32_t start_at_curr)
0N/A#else
0N/Alist_ptr dup_list_head(lp, start_at_curr)
0N/A list_ptr lp;
0N/A int32_t start_at_curr;
0N/A#endif
0N/A{
0N/A list_ptr new_list;
0N/A
0N/A if ((new_list = (list_ptr) malloc( sizeof( list_item))) == NULL) {
0N/A
0N/A return (list_ptr)NULL;
0N/A }
0N/A new_list->next = start_at_curr ? lp->ptr.curr : lp->next;
0N/A new_list->ptr.curr = lp->ptr.curr;
0N/A
0N/A return new_list;
0N/A}
0N/A
0N/A
0N/A/** ------------------------------------------------------------------------
0N/A Returns the number of items in the list.
0N/A -------------------------------------------------------------------- **/
0N/A#if NeedFunctionPrototypes
0N/Auint32_t list_length(list_ptr lp)
0N/A#else
0N/Auint32_t list_length(lp)
0N/A list_ptr lp;
0N/A#endif
0N/A{
0N/A uint32_t count = 0;
0N/A
0N/A while (lp->next) {
0N/A count++;
0N/A lp = lp->next;
0N/A }
0N/A
0N/A return count;
0N/A}
0N/A
0N/A
0N/A/** ------------------------------------------------------------------------
0N/A Scans thru list, looking for a node whose ptr.item is equal to
0N/A the "item" passed in. "Equal" here means the same address - no
0N/A attempt is made to match equivalent values stored in different
0N/A locations. If a match is found, that node is deleted from the
0N/A list. Storage for the node is freed, but not for the item itself.
0N/A Returns a pointer to the item, so the caller can free it if it
0N/A so desires. If a match is not found, returns NULL.
0N/A -------------------------------------------------------------------- **/
0N/A#if NeedFunctionPrototypes
0N/Avoid *delete_from_list(list_ptr lp, void *item)
0N/A#else
0N/Avoid *delete_from_list(lp, item)
0N/A list_ptr lp;
0N/A void *item;
0N/A#endif
0N/A{
0N/A list_ptr new_next;
0N/A
0N/A while (lp->next) {
0N/A if (lp->next->ptr.item == item) {
0N/A new_next = lp->next->next;
0N/A free (lp->next);
0N/A lp->next = new_next;
0N/A
0N/A return item;
0N/A }
0N/A lp = lp->next;
0N/A }
0N/A
0N/A return NULL;
0N/A}
0N/A
0N/A
0N/A/** ------------------------------------------------------------------------
0N/A Deletes each node in the list *except the head*. This allows
0N/A the deletion of lists where the head is not malloced or created
0N/A with new_list(). If free_items is true, each item pointed to
0N/A from the node is freed, in addition to the node itself.
0N/A -------------------------------------------------------------------- **/
0N/A#if NeedFunctionPrototypes
0N/Avoid delete_list(list_ptr lp, int32_t free_items)
0N/A#else
0N/Avoid delete_list(lp, free_items)
0N/A list_ptr lp;
0N/A int32_t free_items;
0N/A#endif
0N/A{
0N/A list_ptr del_node;
0N/A void *item;
0N/A
0N/A while (lp->next) {
0N/A del_node = lp->next;
0N/A item = del_node->ptr.item;
0N/A lp->next = del_node->next;
0N/A free (del_node);
0N/A if (free_items) {
0N/A free( item);
0N/A }
0N/A }
0N/A}
0N/A
0N/A#if NeedFunctionPrototypes
0N/Avoid delete_list_destroying(list_ptr lp, void destructor(void *item))
0N/A#else
0N/Avoid delete_list_destroying(lp, destructor)
0N/A list_ptr lp;
0N/A void (*destructor)();
0N/A#endif
0N/A{
0N/A list_ptr del_node;
0N/A void *item;
0N/A
0N/A while (lp->next) {
0N/A del_node = lp->next;
0N/A item = del_node->ptr.item;
0N/A lp->next = del_node->next;
0N/A free( del_node);
0N/A if (destructor) {
0N/A destructor( item);
0N/A }
0N/A }
0N/A}
0N/A
0N/A
0N/A/** ------------------------------------------------------------------------
0N/A Returns a ptr to the first *item* (not list node) in the list.
0N/A Sets the list head node's curr ptr to the first node in the list.
0N/A Returns NULL if the list is empty.
0N/A -------------------------------------------------------------------- **/
0N/A#if NeedFunctionPrototypes
0N/Avoid * first_in_list(list_ptr lp)
0N/A#else
0N/Avoid * first_in_list(lp)
0N/A list_ptr lp;
0N/A#endif
0N/A{
0N/A if (! lp) {
0N/A
0N/A return NULL;
0N/A }
0N/A lp->ptr.curr = lp->next;
0N/A
0N/A return lp->ptr.curr ? lp->ptr.curr->ptr.item : NULL;
0N/A}
0N/A
0N/A/** ------------------------------------------------------------------------
0N/A Returns a ptr to the next *item* (not list node) in the list.
0N/A Sets the list head node's curr ptr to the next node in the list.
0N/A first_in_list must have been called prior.
0N/A Returns NULL if no next item.
0N/A -------------------------------------------------------------------- **/
0N/A#if NeedFunctionPrototypes
0N/Avoid * next_in_list(list_ptr lp)
0N/A#else
0N/Avoid * next_in_list(lp)
0N/A list_ptr lp;
0N/A#endif
0N/A{
0N/A if (! lp) {
0N/A
0N/A return NULL;
0N/A }
0N/A if (lp->ptr.curr) {
0N/A lp->ptr.curr = lp->ptr.curr->next;
0N/A }
0N/A
0N/A return lp->ptr.curr ? lp->ptr.curr->ptr.item : NULL;
0N/A}
0N/A
0N/A#if NeedFunctionPrototypes
0N/Aint32_t list_is_empty(list_ptr lp)
0N/A#else
0N/Aint32_t list_is_empty(lp)
0N/A list_ptr lp;
0N/A#endif
0N/A{
0N/A return (lp == NULL || lp->next == NULL);
0N/A}