aboutsummaryrefslogtreecommitdiffstats
path: root/cphidgetlist.c
blob: ed5bea16f21a4eecc4c1d9df6d686ce043842a75 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#include "stdafx.h"
#include "cphidgetlist.h"

/* Adds an element to a list - Duplicates are not allowed.
 * Return:	EPHIDGET_OK on success
 *			EPHIDGET_DUPLICATE if the element already exists in the list
 */
int CList_addToList(CListHandle *list, void *element, 
	int (*compare_fptr)(void *element1, void *element2))
{
	int result = 0;
	CListHandle trav = 0, newentry = 0;

	TESTPTRS(list, element)

	/* The very first thing we do is make sure none of these already exist in the list */
	result = CList_findInList(*list, element, compare_fptr, NULL);
	switch (result) {
		case EPHIDGET_OK:
			return EPHIDGET_DUPLICATE;
		case EPHIDGET_NOTFOUND:
			break;
		default:
			return result;
	}

	newentry = (CListHandle)malloc(sizeof(CList));
	if (!newentry) return EPHIDGET_NOMEMORY;
	ZEROMEM(newentry, sizeof(CList));

	newentry->next = 0;
	newentry->element = element;

	if (!*list)
		*list = newentry;
	else
	{
		for (trav = *list; trav->next; trav = trav->next);
		trav->next = newentry;
	}
	return EPHIDGET_OK;
}

/* this returns success even if the element is not found in the list
 * this also removes duplicates.
 *
 * but! if we find in the list the exact element, rather then just a match, we need to free it after! 
 * interating, or the compare function will croak!
 */
int CList_removeFromList(CListHandle *list, void *element, 
	int (*compare_fptr)(void *element1, void *element2),
	int freeDevice, void (*free_fptr)(void *element))
{
	CListHandle traverse = 0, last = 0;
	int freeElement = PFALSE;

	TESTPTRS(list, element)

	for (traverse=*list; traverse; traverse = traverse->next) {
		if(compare_fptr(element, traverse->element)) {
			if(traverse == *list) {
				*list = traverse->next;
				if(freeDevice && traverse->element)
				{
					// don't free element in the middle of iterating!
					if(traverse->element == element)
						freeElement=PTRUE;
					else
						free_fptr(traverse->element);
					traverse->element = 0;
				}
				free(traverse); traverse = NULL;
				traverse=*list;
				break;
			}
			else {
				last->next=traverse->next;
				if(freeDevice && traverse->element)
				{
					// don't free element in the middle of iterating!
					if(traverse->element == element)
						freeElement=PTRUE;
					else
						free_fptr(traverse->element);
					traverse->element = 0;
				}
				free(traverse); traverse = NULL;
				traverse=last;
			}
		}
		last = traverse;
	}
	
	/* element itself was found in the list, and we want it freed - free it here */
	if(freeElement)
		free_fptr(element);

	return EPHIDGET_OK;
}

/* this takes any list, and frees all of the list element, 
	and can also free the elements that they point to */
int CList_emptyList(CListHandle *list, int freeDevices, void (*free_fptr)(void *element))
{
	CListHandle last = 0, traverse = 0;

	TESTPTR(list)

	last = 0;
	for(traverse = *list; traverse; last = traverse, traverse = traverse->next)
	{
		if(traverse->element && freeDevices)
		{
			free_fptr(traverse->element);
			traverse->element = 0;
		}
		if(last)
		{
			free(last); last = NULL;
		}
	}
	if(last)
	{
		free(last); last = NULL;
	}

	*list = 0;

	return EPHIDGET_OK;
}

/* returns EPHIDGET_OK if the device is in the list */
int CList_findInList(CListHandle list, void *element, 
	int (*compare_fptr)(void *element1, void *element2), void **found_element)
{
	CListHandle trav = 0;

	TESTPTR(element)

	for (trav=list; trav; trav = trav->next) {
		if(compare_fptr(element, trav->element)) {
			if(found_element) *found_element = trav->element;
			return EPHIDGET_OK;
		}
	}
	return EPHIDGET_NOTFOUND;
}