Replace current_reply generic queue with hand-written version. No generic queues...
[free-sw/xcb/libxcb] / src / xcb_list.c
1 /* Copyright (C) 2001-2004 Bart Massey and Jamey Sharp.
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining a
4  * copy of this software and associated documentation files (the "Software"),
5  * to deal in the Software without restriction, including without limitation
6  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
7  * and/or sell copies of the Software, and to permit persons to whom the
8  * Software is furnished to do so, subject to the following conditions:
9  * 
10  * The above copyright notice and this permission notice shall be included in
11  * all copies or substantial portions of the Software.
12  * 
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16  * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
17  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19  * 
20  * Except as contained in this notice, the names of the authors or their
21  * institutions shall not be used in advertising or otherwise to promote the
22  * sale, use or other dealings in this Software without prior written
23  * authorization from the authors.
24  */
25
26 /* A generic implementation of a list of void-pointers. */
27
28 #include <stdlib.h>
29
30 #include "xcb.h"
31 #include "xcbint.h"
32
33 typedef struct node {
34     struct node *next;
35     void *data;
36 } node;
37
38 struct _xcb_list {
39     node *head;
40     node **tail;
41 };
42
43 /* Private interface */
44
45 _xcb_list *_xcb_list_new()
46 {
47     _xcb_list *list;
48     list = malloc(sizeof(_xcb_list));
49     if(!list)
50         return 0;
51     list->head = 0;
52     list->tail = &list->head;
53     return list;
54 }
55
56 static void _xcb_list_clear(_xcb_list *list, XCBListFreeFunc do_free)
57 {
58     void *tmp;
59     while((tmp = _xcb_list_remove_head(list)))
60         if(do_free)
61             do_free(tmp);
62 }
63
64 void _xcb_list_delete(_xcb_list *list, XCBListFreeFunc do_free)
65 {
66     if(!list)
67         return;
68     _xcb_list_clear(list, do_free);
69     free(list);
70 }
71
72 int _xcb_list_insert(_xcb_list *list, void *data)
73 {
74     node *cur;
75     cur = malloc(sizeof(node));
76     if(!cur)
77         return 0;
78     cur->data = data;
79
80     cur->next = list->head;
81     list->head = cur;
82     return 1;
83 }
84
85 int _xcb_list_append(_xcb_list *list, void *data)
86 {
87     node *cur;
88     cur = malloc(sizeof(node));
89     if(!cur)
90         return 0;
91     cur->data = data;
92     cur->next = 0;
93
94     *list->tail = cur;
95     list->tail = &cur->next;
96     return 1;
97 }
98
99 void *_xcb_list_peek_head(_xcb_list *list)
100 {
101     if(!list->head)
102         return 0;
103     return list->head->data;
104 }
105
106 void *_xcb_list_remove_head(_xcb_list *list)
107 {
108     void *ret;
109     node *tmp = list->head;
110     if(!tmp)
111         return 0;
112     ret = tmp->data;
113     list->head = tmp->next;
114     if(!list->head)
115         list->tail = &list->head;
116     free(tmp);
117     return ret;
118 }
119
120 void *_xcb_list_remove(_xcb_list *list, int (*cmp)(const void *, const void *), const void *data)
121 {
122     node **cur;
123     for(cur = &list->head; *cur; cur = &(*cur)->next)
124         if(cmp(data, (*cur)->data))
125         {
126             node *tmp = *cur;
127             void *ret = (*cur)->data;
128             *cur = (*cur)->next;
129             if(!*cur)
130                 list->tail = cur;
131
132             free(tmp);
133             return ret;
134         }
135     return 0;
136 }
137
138 void *_xcb_list_find(_xcb_list *list, int (*cmp)(const void *, const void *), const void *data)
139 {
140     node *cur;
141     for(cur = list->head; cur; cur = cur->next)
142         if(cmp(data, cur->data))
143             return cur->data;
144     return 0;
145 }
146
147 typedef struct {
148     unsigned int key;
149     void *value;
150 } map_pair;
151
152 _xcb_map *_xcb_map_new(void) __attribute__ ((alias ("_xcb_list_new")));
153
154 void _xcb_map_delete(_xcb_map *q, XCBListFreeFunc do_free)
155 {
156     map_pair *tmp;
157     if(!q)
158         return;
159     while((tmp = _xcb_list_remove_head(q)))
160     {
161         if(do_free)
162             do_free(tmp->value);
163         free(tmp);
164     }
165     free(q);
166 }
167
168 int _xcb_map_put(_xcb_map *q, unsigned int key, void *data)
169 {
170     map_pair *cur = malloc(sizeof(map_pair));
171     if(!cur)
172         return 0;
173     cur->key = key;
174     cur->value = data;
175     if(!_xcb_list_append(q, cur))
176     {
177         free(cur);
178         return 0;
179     }
180     return 1;
181 }
182
183 static int match_map_pair(const void *key, const void *pair)
184 {
185     return ((map_pair *) pair)->key == *(unsigned int *) key;
186 }
187
188 void *_xcb_map_get(_xcb_map *q, unsigned int key)
189 {
190     map_pair *cur = _xcb_list_find(q, match_map_pair, &key);
191     if(!cur)
192         return 0;
193     return cur->value;
194 }
195
196 void *_xcb_map_remove(_xcb_map *q, unsigned int key)
197 {
198     map_pair *cur = _xcb_list_remove(q, match_map_pair, &key);
199     void *ret;
200     if(!cur)
201         return 0;
202     ret = cur->value;
203     free(cur);
204     return ret;
205 }