1 /* Simple dictionary implementation using a linked list.
2 * FIXME: a skip list would be faster.
4 * Copyright 2005 Juan Lang
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "dictionary.h"
25 #include "wine/debug.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(storage
);
29 struct dictionary_entry
33 struct dictionary_entry
*next
;
41 struct dictionary_entry
*head
;
45 struct dictionary
*dictionary_create(comparefunc c
, destroyfunc d
, void *extra
)
47 struct dictionary
*ret
;
49 TRACE("(%p, %p, %p)\n", c
, d
, extra
);
52 ret
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct dictionary
));
61 TRACE("returning %p\n", ret
);
65 void dictionary_destroy(struct dictionary
*d
)
70 struct dictionary_entry
*p
;
72 for (p
= d
->head
; p
; )
74 struct dictionary_entry
*next
= p
->next
;
77 d
->destroy(p
->key
, p
->value
, d
->extra
);
78 HeapFree(GetProcessHeap(), 0, p
);
81 HeapFree(GetProcessHeap(), 0, d
);
85 UINT
dictionary_num_entries(struct dictionary
*d
)
87 return d
? d
->num_entries
: 0;
90 /* Returns the address of the pointer to the node containing k. (It returns
91 * the address of either h->head or the address of the next member of the
92 * prior node. It's useful when you want to delete.)
93 * Assumes h and prev are not NULL.
95 static struct dictionary_entry
**dictionary_find_internal(struct dictionary
*d
,
98 struct dictionary_entry
**ret
= NULL
;
99 struct dictionary_entry
*p
;
102 /* special case for head containing the desired element */
103 if (d
->head
&& d
->comp(k
, d
->head
->key
, d
->extra
) == 0)
105 for (p
= d
->head
; !ret
&& p
&& p
->next
; p
= p
->next
)
107 if (d
->comp(k
, p
->next
->key
, d
->extra
) == 0)
113 void dictionary_insert(struct dictionary
*d
, const void *k
, const void *v
)
115 struct dictionary_entry
**prior
;
117 TRACE("(%p, %p, %p)\n", d
, k
, v
);
120 if ((prior
= dictionary_find_internal(d
, k
)))
123 d
->destroy((*prior
)->key
, (*prior
)->value
, d
->extra
);
124 (*prior
)->key
= (void *)k
;
125 (*prior
)->value
= (void *)v
;
129 struct dictionary_entry
*elem
= HeapAlloc(GetProcessHeap(), 0,
130 sizeof(struct dictionary_entry
));
134 elem
->key
= (void *)k
;
135 elem
->value
= (void *)v
;
136 elem
->next
= d
->head
;
142 BOOL
dictionary_find(struct dictionary
*d
, const void *k
, void **value
)
144 struct dictionary_entry
**prior
;
147 TRACE("(%p, %p, %p)\n", d
, k
, value
);
152 if ((prior
= dictionary_find_internal(d
, k
)))
154 *value
= (*prior
)->value
;
157 TRACE("returning %d (%p)\n", ret
, *value
);
161 void dictionary_remove(struct dictionary
*d
, const void *k
)
163 struct dictionary_entry
**prior
, *temp
;
165 TRACE("(%p, %p)\n", d
, k
);
168 if ((prior
= dictionary_find_internal(d
, k
)))
172 d
->destroy((*prior
)->key
, (*prior
)->value
, d
->extra
);
173 *prior
= (*prior
)->next
;
174 HeapFree(GetProcessHeap(), 0, temp
);
179 void dictionary_enumerate(struct dictionary
*d
, enumeratefunc e
, void *closure
)
181 struct dictionary_entry
*p
;
183 TRACE("(%p, %p, %p)\n", d
, e
, closure
);
188 for (p
= d
->head
; p
; p
= p
->next
)
189 if (!e(p
->key
, p
->value
, d
->extra
, closure
))