source: mainline/uspace/lib/c/include/adt/int_map.h@ 4edd39fc

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 4edd39fc was 2544442, checked in by Jakub Jermar <jakub@…>, 15 years ago

Fix doxygen doc groups (libc vs. net) and header guards.

  • Property mode set to 100644
File size: 8.9 KB
Line 
1/*
2 * Copyright (c) 2009 Lukas Mejdrech
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup libc
30 * @{
31 */
32
33/** @file
34 * Integer to generic type map.
35 */
36
37#ifndef LIBC_INT_MAP_H_
38#define LIBC_INT_MAP_H_
39
40#include <errno.h>
41#include <malloc.h>
42#include <mem.h>
43#include <unistd.h>
44
45/** Internal magic value for a&nbsp;map consistency check.
46 */
47#define INT_MAP_MAGIC_VALUE 0x11223344
48
49/** Internal magic value for an item consistency check.
50 */
51#define INT_MAP_ITEM_MAGIC_VALUE 0x55667788
52
53/** Integer to generic type map declaration.
54 * @param[in] name Name of the map.
55 * @param[in] type Inner object type.
56 */
57#define INT_MAP_DECLARE(name, type) \
58 \
59typedef struct name name##_t; \
60typedef name##_t * name##_ref; \
61typedef struct name##_item name##_item_t; \
62typedef name##_item_t * name##_item_ref; \
63 \
64struct name##_item{ \
65 int key; \
66 type * value; \
67 int magic; \
68}; \
69 \
70struct name{ \
71 int size; \
72 int next; \
73 name##_item_ref items; \
74 int magic; \
75}; \
76 \
77int name##_add(name##_ref map, int key, type * value); \
78void name##_clear(name##_ref map); \
79int name##_count(name##_ref map); \
80void name##_destroy(name##_ref map); \
81void name##_exclude(name##_ref map, int key); \
82void name##_exclude_index(name##_ref map, int index); \
83type * name##_find(name##_ref map, int key); \
84int name##_update(name##_ref map, int key, int new_key); \
85type * name##_get_index(name##_ref map, int index); \
86int name##_initialize(name##_ref map); \
87int name##_is_valid(name##_ref map); \
88void name##_item_destroy(name##_item_ref item); \
89int name##_item_is_valid(name##_item_ref item);
90
91/** Integer to generic type map implementation.
92 * Should follow declaration with the same parameters.
93 * @param[in] name Name of the map.
94 * @param[in] type Inner object type.
95 */
96#define INT_MAP_IMPLEMENT(name, type) \
97 \
98int name##_add(name##_ref map, int key, type * value){ \
99 if(name##_is_valid(map)){ \
100 if(map->next == (map->size - 1)){ \
101 name##_item_ref tmp; \
102 \
103 tmp = (name##_item_ref) realloc(map->items, sizeof(name##_item_t) * 2 * map->size); \
104 if(! tmp){ \
105 return ENOMEM; \
106 } \
107 map->size *= 2; \
108 map->items = tmp; \
109 } \
110 map->items[map->next].key = key; \
111 map->items[map->next].value = value; \
112 map->items[map->next].magic = INT_MAP_ITEM_MAGIC_VALUE; \
113 ++ map->next; \
114 map->items[map->next].magic = 0; \
115 return map->next - 1; \
116 } \
117 return EINVAL; \
118} \
119 \
120void name##_clear(name##_ref map){ \
121 if(name##_is_valid(map)){ \
122 int index; \
123 \
124/* map->magic = 0;*/ \
125 for(index = 0; index < map->next; ++ index){ \
126 if(name##_item_is_valid(&(map->items[index]))){ \
127 name##_item_destroy(&(map->items[index])); \
128 } \
129 } \
130 map->next = 0; \
131 map->items[map->next].magic = 0; \
132/* map->magic = INT_MAP_MAGIC_VALUE;*/ \
133 } \
134} \
135 \
136int name##_count(name##_ref map){ \
137 return name##_is_valid(map) ? map->next : -1; \
138} \
139 \
140void name##_destroy(name##_ref map){ \
141 if(name##_is_valid(map)){ \
142 int index; \
143 \
144 map->magic = 0; \
145 for(index = 0; index < map->next; ++ index){ \
146 if(name##_item_is_valid(&(map->items[index]))){ \
147 name##_item_destroy(&(map->items[index])); \
148 } \
149 } \
150 free(map->items); \
151 } \
152} \
153 \
154void name##_exclude(name##_ref map, int key){ \
155 if(name##_is_valid(map)){ \
156 int index; \
157 \
158 for(index = 0; index < map->next; ++ index){ \
159 if(name##_item_is_valid(&(map->items[index])) && (map->items[index].key == key)){ \
160 name##_item_destroy(&(map->items[index])); \
161 } \
162 } \
163 } \
164} \
165 \
166void name##_exclude_index(name##_ref map, int index){ \
167 if(name##_is_valid(map) && (index >= 0) && (index < map->next) && name##_item_is_valid(&(map->items[index]))){ \
168 name##_item_destroy(&(map->items[index])); \
169 } \
170} \
171 \
172type * name##_find(name##_ref map, int key){ \
173 if(name##_is_valid(map)){ \
174 int index; \
175 \
176 for(index = 0; index < map->next; ++ index){ \
177 if(name##_item_is_valid(&(map->items[index])) && (map->items[index].key == key)){ \
178 return map->items[index].value; \
179 } \
180 } \
181 } \
182 return NULL; \
183} \
184 \
185int name##_update(name##_ref map, int key, int new_key){ \
186 if(name##_is_valid(map)){ \
187 int index; \
188 \
189 for(index = 0; index < map->next; ++ index){ \
190 if(name##_item_is_valid(&(map->items[index]))){ \
191 if(map->items[index].key == new_key){ \
192 return EEXIST; \
193 }else if(map->items[index].key == key){ \
194 map->items[index].key = new_key; \
195 return EOK; \
196 } \
197 } \
198 } \
199 } \
200 return ENOENT; \
201} \
202 \
203type * name##_get_index(name##_ref map, int index){ \
204 if(name##_is_valid(map) && (index >= 0) && (index < map->next) && name##_item_is_valid(&(map->items[index]))){ \
205 return map->items[index].value; \
206 } \
207 return NULL; \
208} \
209 \
210int name##_initialize(name##_ref map){ \
211 if(! map){ \
212 return EINVAL; \
213 } \
214 map->size = 2; \
215 map->next = 0; \
216 map->items = (name##_item_ref) malloc(sizeof(name##_item_t) * map->size); \
217 if(! map->items){ \
218 return ENOMEM; \
219 } \
220 map->items[map->next].magic = 0; \
221 map->magic = INT_MAP_MAGIC_VALUE; \
222 return EOK; \
223} \
224 \
225int name##_is_valid(name##_ref map){ \
226 return map && (map->magic == INT_MAP_MAGIC_VALUE); \
227} \
228 \
229void name##_item_destroy(name##_item_ref item){ \
230 if(name##_item_is_valid(item)){ \
231 item->magic = 0; \
232 if(item->value){ \
233 free(item->value); \
234 item->value = NULL; \
235 } \
236 } \
237} \
238 \
239int name##_item_is_valid(name##_item_ref item){ \
240 return item && (item->magic == INT_MAP_ITEM_MAGIC_VALUE); \
241}
242
243#endif
244
245/** @}
246 */
247
Note: See TracBrowser for help on using the repository browser.