00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00037 #ifndef LIBC_INT_MAP_H_
00038 #define LIBC_INT_MAP_H_
00039
00040 #include <errno.h>
00041 #include <malloc.h>
00042 #include <mem.h>
00043 #include <unistd.h>
00044
00046 #define INT_MAP_MAGIC_VALUE 0x11223344
00047
00049 #define INT_MAP_ITEM_MAGIC_VALUE 0x55667788
00050
00052 #define DTOR_T(identifier) \
00053 void (*identifier)(const void *)
00054
00060 #define INT_MAP_DECLARE(name, type) \
00061 typedef struct name name##_t; \
00062 typedef struct name##_item name##_item_t; \
00063 \
00064 struct name##_item { \
00065 int key; \
00066 type *value; \
00067 int magic; \
00068 }; \
00069 \
00070 struct name { \
00071 int size; \
00072 int next; \
00073 name##_item_t *items; \
00074 int magic; \
00075 }; \
00076 \
00077 int name##_add(name##_t *, int, type *); \
00078 void name##_clear(name##_t *, DTOR_T()); \
00079 int name##_count(name##_t *); \
00080 void name##_destroy(name##_t *, DTOR_T()); \
00081 void name##_exclude(name##_t *, int, DTOR_T()); \
00082 void name##_exclude_index(name##_t *, int, DTOR_T()); \
00083 type *name##_find(name##_t *, int); \
00084 int name##_update(name##_t *, int, int); \
00085 type *name##_get_index(name##_t *, int); \
00086 int name##_initialize(name##_t *); \
00087 int name##_is_valid(name##_t *); \
00088 void name##_item_destroy(name##_item_t *, DTOR_T()); \
00089 int name##_item_is_valid(name##_item_t *);
00090
00098 #define INT_MAP_IMPLEMENT(name, type) \
00099 int name##_add(name##_t *map, int key, type *value) \
00100 { \
00101 if (name##_is_valid(map)) { \
00102 if (map->next == (map->size - 1)) { \
00103 name##_item_t *tmp; \
00104 tmp = (name##_item_t *) realloc(map->items, \
00105 sizeof(name##_item_t) * 2 * map->size); \
00106 if (!tmp) \
00107 return ENOMEM; \
00108 map->size *= 2; \
00109 map->items = tmp; \
00110 } \
00111 map->items[map->next].key = key; \
00112 map->items[map->next].value = value; \
00113 map->items[map->next].magic = INT_MAP_ITEM_MAGIC_VALUE; \
00114 ++map->next; \
00115 map->items[map->next].magic = 0; \
00116 return map->next - 1; \
00117 } \
00118 return EINVAL; \
00119 } \
00120 \
00121 void name##_clear(name##_t *map, DTOR_T(dtor)) \
00122 { \
00123 if (name##_is_valid(map)) { \
00124 int index; \
00125 for (index = 0; index < map->next; ++index) { \
00126 if (name##_item_is_valid(&map->items[index])) { \
00127 name##_item_destroy( \
00128 &map->items[index], dtor); \
00129 } \
00130 } \
00131 map->next = 0; \
00132 map->items[map->next].magic = 0; \
00133 } \
00134 } \
00135 \
00136 int name##_count(name##_t *map) \
00137 { \
00138 return name##_is_valid(map) ? map->next : -1; \
00139 } \
00140 \
00141 void name##_destroy(name##_t *map, DTOR_T(dtor)) \
00142 { \
00143 if (name##_is_valid(map)) { \
00144 int index; \
00145 map->magic = 0; \
00146 for (index = 0; index < map->next; ++index) { \
00147 if (name##_item_is_valid(&map->items[index])) { \
00148 name##_item_destroy( \
00149 &map->items[index], dtor); \
00150 } \
00151 } \
00152 free(map->items); \
00153 } \
00154 } \
00155 \
00156 void name##_exclude(name##_t *map, int key, DTOR_T(dtor)) \
00157 { \
00158 if (name##_is_valid(map)) { \
00159 int index; \
00160 for (index = 0; index < map->next; ++index) { \
00161 if (name##_item_is_valid(&map->items[index]) && \
00162 (map->items[index].key == key)) { \
00163 name##_item_destroy( \
00164 &map->items[index], dtor); \
00165 } \
00166 } \
00167 } \
00168 } \
00169 \
00170 void name##_exclude_index(name##_t *map, int index, DTOR_T(dtor)) \
00171 { \
00172 if (name##_is_valid(map) && (index >= 0) && \
00173 (index < map->next) && \
00174 name##_item_is_valid(&map->items[index])) { \
00175 name##_item_destroy(&map->items[index], dtor); \
00176 } \
00177 } \
00178 \
00179 type *name##_find(name##_t *map, int key) \
00180 { \
00181 if (name##_is_valid(map)) { \
00182 int index; \
00183 for (index = 0; index < map->next; ++index) { \
00184 if (name##_item_is_valid(&map->items[index]) && \
00185 (map->items[index].key == key)) { \
00186 return map->items[index].value; \
00187 } \
00188 } \
00189 } \
00190 return NULL; \
00191 } \
00192 \
00193 int name##_update(name##_t *map, int key, int new_key) \
00194 { \
00195 if (name##_is_valid(map)) { \
00196 int index; \
00197 for (index = 0; index < map->next; ++index) { \
00198 if (name##_item_is_valid(&map->items[index])) { \
00199 if (map->items[index].key == new_key) \
00200 return EEXIST; \
00201 if (map->items[index].key == key) { \
00202 map->items[index].key = \
00203 new_key; \
00204 return EOK; \
00205 } \
00206 } \
00207 } \
00208 } \
00209 return ENOENT; \
00210 } \
00211 \
00212 type *name##_get_index(name##_t *map, int index) \
00213 { \
00214 if (name##_is_valid(map) && (index >= 0) && \
00215 (index < map->next) && \
00216 name##_item_is_valid(&map->items[index])) { \
00217 return map->items[index].value; \
00218 } \
00219 return NULL; \
00220 } \
00221 \
00222 int name##_initialize(name##_t *map) \
00223 { \
00224 if (!map) \
00225 return EINVAL; \
00226 map->size = 2; \
00227 map->next = 0; \
00228 map->items = (name##_item_t *) malloc(sizeof(name##_item_t) * \
00229 map->size); \
00230 if (!map->items) \
00231 return ENOMEM; \
00232 map->items[map->next].magic = 0; \
00233 map->magic = INT_MAP_MAGIC_VALUE; \
00234 return EOK; \
00235 } \
00236 \
00237 int name##_is_valid(name##_t *map) \
00238 { \
00239 return map && (map->magic == INT_MAP_MAGIC_VALUE); \
00240 } \
00241 \
00242 void name##_item_destroy(name##_item_t *item, DTOR_T(dtor)) \
00243 { \
00244 if (name##_item_is_valid(item)) { \
00245 item->magic = 0; \
00246 if (item->value) { \
00247 if (dtor) \
00248 dtor(item->value); \
00249 item->value = NULL; \
00250 } \
00251 } \
00252 } \
00253 \
00254 int name##_item_is_valid(name##_item_t *item) \
00255 { \
00256 return item && (item->magic == INT_MAP_ITEM_MAGIC_VALUE); \
00257 }
00258
00259 #endif
00260