xref: /illumos-gate/usr/src/cmd/sgs/common/alist.c (revision fb12490a)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
55aefb655Srie  * Common Development and Distribution License (the "License").
65aefb655Srie  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
215aefb655Srie 
227c478bd9Sstevel@tonic-gate /*
2356deab07SRod Evans  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25cce0e03bSab  */
26cce0e03bSab #include <sgs.h>
27cce0e03bSab #include <string.h>
28cce0e03bSab #include <stdio.h>
29cce0e03bSab #include <sys/debug.h>
30cce0e03bSab 
31cce0e03bSab /*
327c478bd9Sstevel@tonic-gate  * Alist manipulation.  An Alist is a list of elements formed into an array.
337c478bd9Sstevel@tonic-gate  * Traversal of the list is an array scan, which because of the locality of
347c478bd9Sstevel@tonic-gate  * each reference is probably more efficient than a link-list traversal.
357c478bd9Sstevel@tonic-gate  *
36cce0e03bSab  * See alist.h for more background information about array lists.
377c478bd9Sstevel@tonic-gate  */
380bc07c75Srie 
390bc07c75Srie /*
40cce0e03bSab  * Insert a value into an array at a specified index:
41cce0e03bSab  *
42cce0e03bSab  *	alist_insert(): Insert an item into an Alist at the specified index
43cce0e03bSab  *	alist_insert_by_offset(): Insert an item into an Alist at the
44cce0e03bSab  *		specified offset relative to the list address.
45cce0e03bSab  *	aplist_insert() Insert a pointer into an APlist at the specified index
46cce0e03bSab  *
47cce0e03bSab  * entry:
48cce0e03bSab  *	Note: All the arguments for all three routines are listed here.
49cce0e03bSab  *	The routine to which a given argument applies is given with
50cce0e03bSab  *	each description.
51cce0e03bSab  *
52cce0e03bSab  *	llp [all] - Address of a pointer to an Alist/APlist. The pointer should
53cce0e03bSab  *		be initialized to NULL before its first use.
54cce0e03bSab  *	datap [alist_insert / aplist_insert] - Pointer to item data, or
55cce0e03bSab  *		NULL. If non-null the data referenced is copied into the
56cce0e03bSab  *		Alist item. Otherwise, the list item is zeroed, and
57cce0e03bSab  *		further initialization is left to the caller.
58cce0e03bSab  *	ptr [aplist_insert] - Pointer to be inserted.
59cce0e03bSab  *	size [alist_insert / alist_insert_by_offset] - Size of an item
60cce0e03bSab  *		in the array list, in bytes. As with any array, A given
61cce0e03bSab  *		Alist can support any item size, but every item in that
62cce0e03bSab  *		list must have the same size.
63cce0e03bSab  *	init_arritems [all] - Initial allocation size: On the first insertion
64cce0e03bSab  *		into the array list, room for init_arritems items is allocated.
65cce0e03bSab  *	idx [alist_insert / aplist_insert] - Index at which to insert the
66cce0e03bSab  *		new item. This index must lie within the existing list,
67cce0e03bSab  *		or be the next index following.
68cce0e03bSab  *	off [alist_insert_by_offset] - Offset at which  to insert the new
69cce0e03bSab  *		item, based from the start of the Alist. The offset of
70cce0e03bSab  *		the first item is ALIST_OFF_DATA.
71cce0e03bSab  *
72cce0e03bSab  * exit:
73cce0e03bSab  *	The item is inserted at the specified position. This operation
74cce0e03bSab  *	can cause memory for the list to be allocated, or reallocated,
75cce0e03bSab  *	either of which will cause the value of the list pointer
76cce0e03bSab  *	to change.
77cce0e03bSab  *
78cce0e03bSab  *	These routines can only fail if unable to allocate memory,
79cce0e03bSab  *	in which case NULL is returned.
80cce0e03bSab  *
81cce0e03bSab  *	If a pointer list (aplist_insert), then the pointer
82cce0e03bSab  *	is stored in the requested index. On success, the address
83cce0e03bSab  *	of the pointer within the list is returned.
84cce0e03bSab  *
85cce0e03bSab  *	If the list contains arbitrary data (not aplist_insert): If datap
86cce0e03bSab  *	is non-NULL, the data it references is copied into the item at
87cce0e03bSab  *	the index. If datap is NULL, the specified item is zeroed.
88cce0e03bSab  *	On success, a pointer to the inserted item is returned.
89cce0e03bSab  *
90cce0e03bSab  *	The  caller must not retain the returned pointer from this
91cce0e03bSab  *	routine across calls to the list module. It is only safe to use
92cce0e03bSab  *	it until the next call to this module for the given list.
93cce0e03bSab  *
940bc07c75Srie  */
957c478bd9Sstevel@tonic-gate void *
alist_insert(Alist ** lpp,const void * datap,size_t size,Aliste init_arritems,Aliste idx)96cce0e03bSab alist_insert(Alist **lpp, const void *datap, size_t size,
97cce0e03bSab     Aliste init_arritems, Aliste idx)
987c478bd9Sstevel@tonic-gate {
99cce0e03bSab 	Alist	*lp = *lpp;
100cce0e03bSab 	char	*addr;
1017c478bd9Sstevel@tonic-gate 
102cce0e03bSab 	/* The size and initial array count need to be non-zero */
103cce0e03bSab 	ASSERT(init_arritems != 0);
104cce0e03bSab 	ASSERT(size != 0);
1057c478bd9Sstevel@tonic-gate 
106cce0e03bSab 	if (lp == NULL) {
107cce0e03bSab 		Aliste bsize;
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate 		/*
110cce0e03bSab 		 * First time here, allocate a new Alist.  Note that the
111cce0e03bSab 		 * Alist al_desc[] entry is defined for 1 element,
112cce0e03bSab 		 * but we actually allocate the number we need.
1137c478bd9Sstevel@tonic-gate 		 */
114cce0e03bSab 		bsize = size * init_arritems;
115cce0e03bSab 		bsize = S_ROUND(bsize, sizeof (void *));
116cce0e03bSab 		bsize = ALIST_OFF_DATA + bsize;
117cce0e03bSab 		if ((lp = malloc((size_t)bsize)) == NULL)
118cce0e03bSab 			return (NULL);
119cce0e03bSab 		lp->al_arritems = init_arritems;
120cce0e03bSab 		lp->al_nitems = 0;
121cce0e03bSab 		lp->al_next = ALIST_OFF_DATA;
122cce0e03bSab 		lp->al_size = size;
123cce0e03bSab 		*lpp = lp;
124cce0e03bSab 	} else {
125cce0e03bSab 		/* We must get the same value for size every time */
126cce0e03bSab 		ASSERT(size == lp->al_size);
127cce0e03bSab 
128cce0e03bSab 		if (lp->al_nitems >= lp->al_arritems) {
129cce0e03bSab 			/*
130cce0e03bSab 			 * The list is full: Increase the memory allocation
131cce0e03bSab 			 * by doubling it.
132cce0e03bSab 			 */
133cce0e03bSab 			Aliste	bsize;
134cce0e03bSab 
135cce0e03bSab 			bsize = lp->al_size * lp->al_arritems * 2;
136cce0e03bSab 			bsize = S_ROUND(bsize, sizeof (void *));
137cce0e03bSab 			bsize = ALIST_OFF_DATA + bsize;
138*fb12490aSRichard Lowe 			if ((lp = realloc(lp, (size_t)bsize)) == NULL)
139cce0e03bSab 				return (NULL);
140cce0e03bSab 			lp->al_arritems *= 2;
141cce0e03bSab 			*lpp = lp;
142cce0e03bSab 		}
1437c478bd9Sstevel@tonic-gate 	}
1447c478bd9Sstevel@tonic-gate 
145cce0e03bSab 	/*
146cce0e03bSab 	 * The caller is not supposed to use an index that
147cce0e03bSab 	 * would introduce a "hole" in the array.
148cce0e03bSab 	 */
149cce0e03bSab 	ASSERT(idx <= lp->al_nitems);
150cce0e03bSab 
151cce0e03bSab 	addr = (idx * lp->al_size) + (char *)lp->al_data;
152cce0e03bSab 
1530bc07c75Srie 	/*
1540bc07c75Srie 	 * An appended item is added to the next available array element.
155cce0e03bSab 	 * An insert at any other spot requires that the data items that
156cce0e03bSab 	 * exist at the point of insertion be shifted down to open a slot.
1570bc07c75Srie 	 */
158cce0e03bSab 	if (idx < lp->al_nitems)
159cce0e03bSab 		(void) memmove(addr + lp->al_size, addr,
160cce0e03bSab 		    (lp->al_nitems - idx) * lp->al_size);
161cce0e03bSab 
162cce0e03bSab 	lp->al_nitems++;
163cce0e03bSab 	lp->al_next += lp->al_size;
164cce0e03bSab 	if (datap != NULL)
165cce0e03bSab 		(void) memcpy(addr, datap, lp->al_size);
166cce0e03bSab 	else
167cce0e03bSab 		(void) memset(addr, 0, lp->al_size);
168cce0e03bSab 	return (addr);
169cce0e03bSab }
170cce0e03bSab 
171cce0e03bSab void *
alist_insert_by_offset(Alist ** lpp,const void * datap,size_t size,Aliste init_arritems,Aliste off)172cce0e03bSab alist_insert_by_offset(Alist **lpp, const void *datap, size_t size,
173cce0e03bSab     Aliste init_arritems, Aliste off)
174cce0e03bSab {
175cce0e03bSab 	Aliste idx;
176cce0e03bSab 
177cce0e03bSab 	if (*lpp == NULL) {
178cce0e03bSab 		ASSERT(off == ALIST_OFF_DATA);
179cce0e03bSab 		idx = 0;
1800bc07c75Srie 	} else {
181cce0e03bSab 		idx = (off - ALIST_OFF_DATA) / (*lpp)->al_size;
182cce0e03bSab 	}
183cce0e03bSab 
184cce0e03bSab 	return (alist_insert(lpp, datap, size, init_arritems, idx));
185cce0e03bSab }
186cce0e03bSab 
187cce0e03bSab void *
aplist_insert(APlist ** lpp,const void * ptr,Aliste init_arritems,Aliste idx)188cce0e03bSab aplist_insert(APlist **lpp, const void *ptr, Aliste init_arritems, Aliste idx)
189cce0e03bSab {
190cce0e03bSab 	APlist	*lp = *lpp;
191cce0e03bSab 
192cce0e03bSab 	/* The initial array count needs to be non-zero */
193cce0e03bSab 	ASSERT(init_arritems != 0);
194cce0e03bSab 
195cce0e03bSab 	if (lp == NULL) {
196cce0e03bSab 		Aliste bsize;
197cce0e03bSab 
198cce0e03bSab 		/*
199cce0e03bSab 		 * First time here, allocate a new APlist.  Note that the
200cce0e03bSab 		 * APlist apl_desc[] entry is defined for 1 element,
201cce0e03bSab 		 * but we actually allocate the number we need.
202cce0e03bSab 		 */
203cce0e03bSab 		bsize = APLIST_OFF_DATA + (sizeof (void *) * init_arritems);
204cce0e03bSab 		if ((lp = malloc((size_t)bsize)) == NULL)
205cce0e03bSab 			return (NULL);
206cce0e03bSab 		lp->apl_arritems = init_arritems;
207cce0e03bSab 		lp->apl_nitems = 0;
208cce0e03bSab 		*lpp = lp;
209cce0e03bSab 	} else if (lp->apl_nitems >= lp->apl_arritems) {
210cce0e03bSab 		/*
211cce0e03bSab 		 * The list is full: Increase the memory allocation
212cce0e03bSab 		 * by doubling it.
213cce0e03bSab 		 */
214cce0e03bSab 		Aliste	bsize;
215cce0e03bSab 
216cce0e03bSab 		bsize = APLIST_OFF_DATA +
217cce0e03bSab 		    (2 * sizeof (void *) * lp->apl_arritems);
218*fb12490aSRichard Lowe 		if ((lp = realloc(lp, (size_t)bsize)) == NULL)
219cce0e03bSab 			return (NULL);
220cce0e03bSab 		lp->apl_arritems *= 2;
221cce0e03bSab 		*lpp = lp;
2220bc07c75Srie 	}
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate 	/*
225cce0e03bSab 	 * The caller is not supposed to use an index that
226cce0e03bSab 	 * would introduce a "hole" in the array.
2277c478bd9Sstevel@tonic-gate 	 */
228cce0e03bSab 	ASSERT(idx <= lp->apl_nitems);
2297c478bd9Sstevel@tonic-gate 
230cce0e03bSab 	/*
231cce0e03bSab 	 * An appended item is added to the next available array element.
232cce0e03bSab 	 * An insert at any other spot requires that the data items that
233cce0e03bSab 	 * exist at the point of insertion be shifted down to open a slot.
234cce0e03bSab 	 */
235cce0e03bSab 	if (idx < lp->apl_nitems)
236cce0e03bSab 		(void) memmove((char *)&lp->apl_data[idx + 1],
237cce0e03bSab 		    (char *)&lp->apl_data[idx],
238cce0e03bSab 		    (lp->apl_nitems - idx) * sizeof (void *));
239cce0e03bSab 
240cce0e03bSab 	lp->apl_nitems++;
241cce0e03bSab 	lp->apl_data[idx] = (void *)ptr;
242cce0e03bSab 	return (&lp->apl_data[idx]);
2437c478bd9Sstevel@tonic-gate }
2447c478bd9Sstevel@tonic-gate 
2450bc07c75Srie /*
246cce0e03bSab  * Append a value to a list. These are convenience wrappers on top
24756deab07SRod Evans  * of the insert operation. See the description of those routine above
248cce0e03bSab  * for details.
2490bc07c75Srie  */
2500bc07c75Srie void *
alist_append(Alist ** lpp,const void * datap,size_t size,Aliste init_arritems)251cce0e03bSab alist_append(Alist **lpp, const void *datap, size_t size,
252cce0e03bSab     Aliste init_arritems)
2530bc07c75Srie {
254cce0e03bSab 	Aliste ndx = ((*lpp) == NULL) ? 0 : (*lpp)->al_nitems;
255cce0e03bSab 
256cce0e03bSab 	return (alist_insert(lpp, datap, size, init_arritems, ndx));
2570bc07c75Srie }
2580bc07c75Srie 
259cce0e03bSab void *
aplist_append(APlist ** lpp,const void * ptr,Aliste init_arritems)260cce0e03bSab aplist_append(APlist **lpp, const void *ptr, Aliste init_arritems)
261cce0e03bSab {
262cce0e03bSab 	Aliste ndx = ((*lpp) == NULL) ? 0 : (*lpp)->apl_nitems;
263cce0e03bSab 
264cce0e03bSab 	return (aplist_insert(lpp, ptr, init_arritems, ndx));
265cce0e03bSab }
266cce0e03bSab 
2677c478bd9Sstevel@tonic-gate /*
268cce0e03bSab  * Delete the item at a specified index/offset, and decrement the variable
269cce0e03bSab  * containing the index:
270cce0e03bSab  *
271cce0e03bSab  *	alist_delete - Delete an item from an Alist at the specified
272cce0e03bSab  *		index.
273cce0e03bSab  *	alist_delete_by_offset - Delete an item from an Alist at the
274cce0e03bSab  *		specified offset from the list pointer.
275cce0e03bSab  *	aplist_delete - Delete a pointer from an APlist at the specified
276cce0e03bSab  *		index.
277cce0e03bSab  *
278cce0e03bSab  * entry:
279cce0e03bSab  *	alp - List to delete item from
280cce0e03bSab  *	idxp - Address of variable containing the index of the
281cce0e03bSab  *		item to delete.
282cce0e03bSab  *	offp - Address of variable containing the offset of the
283cce0e03bSab  *		item to delete.
284cce0e03bSab  *
285cce0e03bSab  * exit:
286cce0e03bSab  *	The item at the position given by (*idxp) or (*offp), depending
287cce0e03bSab  *	on the routine, is removed from the list. Then, the position
288cce0e03bSab  *	variable (*idxp or *offp) is decremented by one item. This is done
289cce0e03bSab  *	to facilitate use of this routine within a TRAVERSE loop.
290cce0e03bSab  *
291cce0e03bSab  * note:
292cce0e03bSab  *	Deleting the last element in an array list is cheap, but
293cce0e03bSab  *	deleting any other item causes a memory copy to occur to
294cce0e03bSab  *	move the following items up. If you intend to traverse the
295cce0e03bSab  *	entire list, deleting every item as you go, it will be cheaper
296cce0e03bSab  *	to omit the delete within the traverse, and then call
297cce0e03bSab  *	the reset function reset() afterwards.
2987c478bd9Sstevel@tonic-gate  */
299cce0e03bSab void
alist_delete(Alist * lp,Aliste * idxp)300cce0e03bSab alist_delete(Alist *lp, Aliste *idxp)
3017c478bd9Sstevel@tonic-gate {
302cce0e03bSab 	Aliste	idx = *idxp;
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate 
305cce0e03bSab 	/* The list must be allocated and the index in range */
306cce0e03bSab 	ASSERT(lp != NULL);
307cce0e03bSab 	ASSERT(idx < lp->al_nitems);
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate 	/*
3107c478bd9Sstevel@tonic-gate 	 * If the element to be removed is not the last entry of the array,
3117c478bd9Sstevel@tonic-gate 	 * slide the following elements over the present element.
3127c478bd9Sstevel@tonic-gate 	 */
313cce0e03bSab 	if (idx < --lp->al_nitems) {
314cce0e03bSab 		char *addr = (idx * lp->al_size) + (char *)lp->al_data;
315cce0e03bSab 
316cce0e03bSab 		(void) memmove(addr, addr + lp->al_size,
317cce0e03bSab 		    (lp->al_nitems - idx) * lp->al_size);
3187c478bd9Sstevel@tonic-gate 	}
319cce0e03bSab 	lp->al_next -= lp->al_size;
320cce0e03bSab 
321cce0e03bSab 	/* Decrement the callers index variable */
322cce0e03bSab 	(*idxp)--;
323cce0e03bSab }
324cce0e03bSab 
325cce0e03bSab void
alist_delete_by_offset(Alist * lp,Aliste * offp)326cce0e03bSab alist_delete_by_offset(Alist *lp, Aliste *offp)
327cce0e03bSab {
328cce0e03bSab 	Aliste idx;
329cce0e03bSab 
330cce0e03bSab 	ASSERT(lp != NULL);
331cce0e03bSab 	idx = (*offp - ALIST_OFF_DATA) / lp->al_size;
332cce0e03bSab 
333cce0e03bSab 	alist_delete(lp, &idx);
334cce0e03bSab 	*offp -= lp->al_size;
335cce0e03bSab }
336cce0e03bSab 
337cce0e03bSab void
aplist_delete(APlist * lp,Aliste * idxp)338cce0e03bSab aplist_delete(APlist *lp, Aliste *idxp)
339cce0e03bSab {
340cce0e03bSab 	Aliste	idx = *idxp;
341cce0e03bSab 
342cce0e03bSab 
343cce0e03bSab 	/* The list must be allocated and the index in range */
344cce0e03bSab 	ASSERT(lp != NULL);
345cce0e03bSab 	ASSERT(idx < lp->apl_nitems);
3467c478bd9Sstevel@tonic-gate 
3477c478bd9Sstevel@tonic-gate 	/*
348cce0e03bSab 	 * If the element to be removed is not the last entry of the array,
349cce0e03bSab 	 * slide the following elements over the present element.
3507c478bd9Sstevel@tonic-gate 	 */
351cce0e03bSab 	if (idx < --lp->apl_nitems)
352cce0e03bSab 		(void) memmove(&lp->apl_data[idx], &lp->apl_data[idx + 1],
353cce0e03bSab 		    (lp->apl_nitems - idx) * sizeof (void *));
3547c478bd9Sstevel@tonic-gate 
355cce0e03bSab 	/* Decrement the callers index variable */
356cce0e03bSab 	(*idxp)--;
3577c478bd9Sstevel@tonic-gate }
3587c478bd9Sstevel@tonic-gate 
3597c478bd9Sstevel@tonic-gate /*
360cce0e03bSab  * Delete the pointer with a specified value from the APlist.
361cce0e03bSab  *
362cce0e03bSab  * entry:
363cce0e03bSab  *	lp - Initialized APlist to delete item from
364cce0e03bSab  *	ptr - Pointer to be deleted.
365cce0e03bSab  *
366cce0e03bSab  * exit:
367cce0e03bSab  *	The list is searched for an item containing the given pointer,
368cce0e03bSab  *	and if a match is found, that item is delted and True (1) returned.
369cce0e03bSab  *	If no match is found, then False (0) is returned.
370cce0e03bSab  *
371cce0e03bSab  * note:
372cce0e03bSab  *	See note for delete operation, above.
3737c478bd9Sstevel@tonic-gate  */
3747c478bd9Sstevel@tonic-gate int
aplist_delete_value(APlist * lp,const void * ptr)375cce0e03bSab aplist_delete_value(APlist *lp, const void *ptr)
3767c478bd9Sstevel@tonic-gate {
377cce0e03bSab 	size_t	idx;
3787c478bd9Sstevel@tonic-gate 
379cce0e03bSab 	/*
380cce0e03bSab 	 * If the pointer is found in the list, use aplist_delete to
381cce0e03bSab 	 * remove it, and we're done.
382cce0e03bSab 	 */
383cce0e03bSab 	for (idx = 0; idx < lp->apl_nitems; idx++)
384cce0e03bSab 		if (ptr == lp->apl_data[idx]) {
385cce0e03bSab 			aplist_delete(lp, &idx);
386cce0e03bSab 			return (1);
3877c478bd9Sstevel@tonic-gate 		}
3887c478bd9Sstevel@tonic-gate 
389cce0e03bSab 	/* If we get here, the item was not in the list */
390cce0e03bSab 	return (0);
391cce0e03bSab }
392cce0e03bSab 
393cce0e03bSab /*
394cce0e03bSab  * Search the APlist for an element with a given value, and
395cce0e03bSab  * if not found, optionally append the element to the end of the list.
396cce0e03bSab  *
397cce0e03bSab  * entry:
398cce0e03bSab  *	lpp, ptr - As per aplist_insert().
399cce0e03bSab  *	init_arritems - As per aplist_insert() if a non-zero value.
400cce0e03bSab  *		A value of zero is special, and is taken to indicate
401cce0e03bSab  *		that no insert operation should be performed if
402cce0e03bSab  *		the item is not found in the list.
403cce0e03bSab  *
404cce0e03bSab  * exit
405cce0e03bSab  *	The given item is compared to every item in the given APlist.
406cce0e03bSab  *	If it is found, ALE_EXISTS is returned.
407cce0e03bSab  *
408cce0e03bSab  *	If it is not found: If init_arr_items is False (0), then
409cce0e03bSab  *	ALE_NOTFOUND is returned. If init_arr_items is True, then
410cce0e03bSab  *	the item is appended to the list, and ALE_CREATE returned on success.
411cce0e03bSab  *
412cce0e03bSab  *	On failure, which can only occur due to memory allocation failure,
413cce0e03bSab  *	ALE_ALLOCFAIL is returned.
414cce0e03bSab  *
415cce0e03bSab  * note:
416cce0e03bSab  *	The test operation used by this routine is a linear
417cce0e03bSab  *	O(N) operation, and is not efficient for more than a
418cce0e03bSab  *	few items.
419cce0e03bSab  */
420cce0e03bSab aplist_test_t
aplist_test(APlist ** lpp,const void * ptr,Aliste init_arritems)421cce0e03bSab aplist_test(APlist **lpp, const void *ptr, Aliste init_arritems)
422cce0e03bSab {
423cce0e03bSab 	APlist	*lp = *lpp;
424cce0e03bSab 	size_t	idx;
425cce0e03bSab 
426cce0e03bSab 	/* Is the pointer already in the list? */
427cce0e03bSab 	if (lp != NULL)
428cce0e03bSab 		for (idx = 0; idx < lp->apl_nitems; idx++)
429cce0e03bSab 			if (ptr == lp->apl_data[idx])
430cce0e03bSab 				return (ALE_EXISTS);
431cce0e03bSab 
432cce0e03bSab 	/* Is this a no-insert case? If so, report that the item is not found */
433cce0e03bSab 	if (init_arritems == 0)
434cce0e03bSab 		return (ALE_NOTFND);
435cce0e03bSab 
436cce0e03bSab 	/* Add it to the end of the list */
437cce0e03bSab 	if (aplist_append(lpp, ptr, init_arritems) == NULL)
438cce0e03bSab 		return (ALE_ALLOCFAIL);
4397c478bd9Sstevel@tonic-gate 	return (ALE_CREATE);
4407c478bd9Sstevel@tonic-gate }
441cce0e03bSab 
442cce0e03bSab /*
443cce0e03bSab  * Reset the given list to its empty state. Any memory allocated by the
444cce0e03bSab  * list is preserved, ready for reuse, but the list is set to its
445cce0e03bSab  * empty state, equivalent to having called the delete operation for
446cce0e03bSab  * every item.
447cce0e03bSab  *
448cce0e03bSab  * Note that no cleanup of the discarded items is done. The caller must
449cce0e03bSab  * take care of any necessary cleanup before calling aplist_reset().
450cce0e03bSab  */
451cce0e03bSab void
alist_reset(Alist * lp)452cce0e03bSab alist_reset(Alist *lp)
453cce0e03bSab {
454cce0e03bSab 	if (lp != NULL) {
455cce0e03bSab 		lp->al_nitems = 0;
456cce0e03bSab 		lp->al_next = ALIST_OFF_DATA;
457cce0e03bSab 	}
458cce0e03bSab }
459cce0e03bSab 
460cce0e03bSab void
aplist_reset(APlist * lp)461cce0e03bSab aplist_reset(APlist *lp)
462cce0e03bSab {
463cce0e03bSab 	if (lp != NULL)
464cce0e03bSab 		lp->apl_nitems = 0;
465cce0e03bSab }
466