2 * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
4 * This file is part of libFirm.
6 * This file may be distributed and/or modified under the terms of the
7 * GNU General Public License version 2 as published by the Free Software
8 * Foundation and appearing in the file LICENSE.GPL included in the
9 * packaging of this file.
11 * Licensees holding valid libFirm Professional Edition licenses may use
12 * this file in accordance with the libFirm Commercial License.
13 * Agreement provided with the Software.
15 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * @author Michael Beck
23 * @brief A linked nodeset.
27 #include "irlinkednodeset.h"
31 static ir_lnk_nodeset_entry_t null_nodeset_entry;
34 #define HashSet ir_lnk_nodeset_t
35 #define HashSetIterator ir_lnk_nodeset_iterator_t
36 #define ValueType ir_lnk_nodeset_entry_t
37 #define NullValue null_nodeset_entry
38 #define KeyType ir_node*
39 #define ConstKeyType const ir_node*
40 #define GetKey(value) (value).node
41 #define InitData(self,value,key) do { (value).node = (key); (value).list.next = NULL; (value).list.prev = NULL; } while (0)
42 #define Hash(self,key) ((unsigned)((key)->node_nr))
43 #define KeysEqual(self,key1,key2) (key1) == (key2)
44 #define SetRangeEmpty(ptr,size) memset(ptr, 0, (size) * sizeof((ptr)[0]))
45 #define EntrySetEmpty(value) (value).node = NULL
46 #define EntrySetDeleted(value) do { (value).node = (ir_node*) -1; list_del(&(value).list); } while (0)
47 #define EntryIsEmpty(value) ((value).node == NULL)
48 #define EntryIsDeleted(value) ((value).node == (ir_node*)-1)
50 #define hashset_init ir_lnk_nodeset_init
51 #define hashset_init_size ir_lnk_nodeset_init_size
52 #define hashset_destroy ir_lnk_nodeset_destroy
53 ir_lnk_nodeset_entry_t *ir_lnk_nodeset_insert_(ir_lnk_nodeset_t *nodeset, ir_node *node);
54 #define hashset_insert ir_lnk_nodeset_insert_
55 #define hashset_remove ir_lnk_nodeset_remove
56 ir_lnk_nodeset_entry_t *ir_lnk_nodeset_find_(const ir_lnk_nodeset_t *nodeset, const ir_node *node);
57 #define hashset_find ir_lnk_nodeset_find_
58 #define hashset_size ir_lnk_nodeset_size
60 #define ADDITIONAL_INIT INIT_LIST_HEAD(&self->elem_list); INIT_LIST_HEAD(&self->all_iters);
61 #define ADDITIONAL_TERM INIT_LIST_HEAD(&self->elem_list); INIT_LIST_HEAD(&self->all_iters);
64 #define HAVE_OWN_RESIZE
72 static void resize(HashSet *self, size_t new_size)
74 HashSetEntry *old_entries = self->entries;
75 HashSetEntry *new_entries;
76 list_head list = self->elem_list;
80 /* allocate a new array with double size */
81 new_entries = Alloc(new_size);
82 SetRangeEmpty(new_entries, new_size);
84 /* use the new array */
85 self->entries = new_entries;
86 self->num_buckets = new_size;
87 self->num_elements = 0;
88 self->num_deleted = 0;
90 self->entries_version++;
92 reset_thresholds(self);
94 assert(!list_empty(&self->elem_list));
95 list.next->prev = &list;
96 list.prev->next = &list;
98 /* reinsert all elements */
99 INIT_LIST_HEAD(&self->elem_list);
100 list_for_each_entry(ValueType, entry, &list, list) {
101 res &= ir_lnk_nodeset_insert(self, EntryGetValue(*entry).node);
103 /* all re-inserted data must be new, if not, we found a node twice ... */
106 /* now we can free the old array */
111 /* Inserts a node into a linked nodeset. */
112 int ir_lnk_nodeset_insert(ir_lnk_nodeset_t *nodeset, ir_node *node)
114 ir_lnk_nodeset_entry_t *entry = ir_lnk_nodeset_insert_(nodeset, node);
116 if (entry->list.next == NULL) {
117 /* we have added a new element */
118 list_add_tail(&entry->list, &nodeset->elem_list);
124 int ir_lnk_nodeset_contains(const ir_lnk_nodeset_t *nodeset, const ir_node *node)
126 return ir_lnk_nodeset_find_(nodeset, node) != NULL;
130 * Initializes a nodeset iterator. Sets the iterator before the first element in
131 * the linked nodeset.
133 * @param iterator Pointer to already allocated iterator memory
134 * @param nodeset Pointer to the nodeset
136 void ir_lnk_nodeset_iterator_init(ir_lnk_nodeset_iterator_t *iterator,
137 const ir_lnk_nodeset_t *nodeset)
139 iterator->iter = nodeset->elem_list.next;
140 iterator->nodeset = nodeset;
144 * Advances the iterator and returns the current element or NULL if all elements
145 * in the linked nodeset have been processed.
146 * @attention It is not allowed to use ir_lnk_nodeset_insert or ir_lnk_nodeset_remove while
147 * iterating over a nodeset.
149 * @param iterator Pointer to the nodeset iterator.
150 * @returns Next element in the nodeset or NULL
152 ir_node *ir_lnk_nodeset_iterator_next(ir_lnk_nodeset_iterator_t *iterator)
155 if (iterator->iter == &iterator->nodeset->elem_list)
158 res = list_entry(iterator->iter, ir_lnk_nodeset_entry_t, list)->node;
159 iterator->iter = iterator->iter->next;
165 * Removes the element the iterator currently points to.
167 * @param nodeset Pointer to the linked nodeset
168 * @param iterator Pointer to the nodeset iterator.
170 void ir_lnk_nodeset_remove_iterator(ir_lnk_nodeset_t *nodeset,
171 ir_lnk_nodeset_iterator_t *iterator)
173 ir_lnk_nodeset_entry_t *rem = list_entry(iterator->iter->prev, ir_lnk_nodeset_entry_t, list);
175 ir_lnk_nodeset_remove(nodeset, rem->node);