Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
34fb42ea793ab226620450a4ef0aa7f755dbda19
[simgrid.git] / src / xbt / lib.c
1 /* lib - a generic library, variation over dictionary                    */
2
3 /* Copyright (c) 2011, 2013-2015. The SimGrid Team.
4  * All rights reserved.                                                     */
5
6 /* This program is free software; you can redistribute it and/or modify it
7  * under the terms of the license (GNU LGPL) which comes with this package. */
8
9 #include <xbt/sysdep.h>
10 #include <xbt/log.h>
11 #include <xbt/lib.h>
12
13 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(xbt_lib, xbt,
14                                 "A dict with keys of type (name, level)");
15
16 xbt_lib_t xbt_lib_new(void)
17 {
18   xbt_lib_t lib;
19   lib = xbt_new(s_xbt_lib_t, 1);
20   lib->dict = xbt_dict_new_homogeneous(xbt_free_f);
21   lib->levels = 0;
22   lib->free_f = NULL;
23   return lib;
24 }
25
26 void xbt_lib_free(xbt_lib_t *plib)
27 {
28   xbt_lib_t lib = *plib;
29   if (lib) {
30     xbt_dict_cursor_t cursor;
31     char *key;
32     void **elts;
33     xbt_dict_foreach (lib->dict, cursor, key, elts) {
34       int i;
35       for (i = 0 ; i < lib->levels ; i++)
36         if (elts[i])
37           lib->free_f[i](elts[i]);
38     }
39     xbt_dict_free(&lib->dict);
40     xbt_free(lib->free_f);
41     xbt_free(lib);
42     *plib = NULL;
43   }
44 }
45
46 int xbt_lib_add_level(xbt_lib_t lib, void_f_pvoid_t free_f)
47 {
48   XBT_DEBUG("xbt_lib_add_level");
49   xbt_assert(xbt_dict_is_empty(lib->dict),
50              "Lib is not empty, cannot add a level");
51   lib->free_f = xbt_realloc(lib->free_f,
52                             sizeof(void_f_pvoid_t) * (lib->levels + 1));
53   lib->free_f[lib->levels] = free_f;
54   return lib->levels++;
55 }
56
57 void xbt_lib_set(xbt_lib_t lib, const char *key, int level, void *obj)
58 {
59   XBT_DEBUG("xbt_lib_set key '%s:%d' with object %p", key, level, obj);
60   void **elts = xbt_dict_get_or_null(lib->dict, key);
61   if (!elts) {
62     elts = xbt_new0(void *, lib->levels);
63     xbt_dict_set(lib->dict, key, elts, NULL);
64   }
65   if (elts[level]) {
66     XBT_DEBUG("Replace %p by %p element under key '%s:%d'",
67               elts[level], obj, key, level);
68     lib->free_f[level](elts[level]);
69   }
70   elts[level] = obj;
71 }
72
73 void xbt_lib_unset(xbt_lib_t lib, const char *key, int level, int invoke_callback)
74 {
75   void **elts = xbt_dict_get_or_null(lib->dict, key);
76   if (!elts) {
77      XBT_WARN("no key %s", key);
78      return;
79   }
80
81   void *obj = elts[level];
82   if (!obj) {
83      XBT_WARN("no key %s at level %d", key, level);
84      return;
85   }
86
87   XBT_DEBUG("Remove %p of key %s at level %d", obj, key, level);
88   elts[level] = NULL;
89
90   /* check if there still remains any elements of this key */
91   int empty = 1;
92   int i;
93   for (i = 0; i < lib->levels && empty; i++) {
94      if (elts[i] != NULL)
95        empty = 0;
96   }
97   if (empty) {
98     /* there is no element at any level, so delete the key */
99     xbt_dict_remove(lib->dict, key);
100   }
101
102   if (invoke_callback)
103     lib->free_f[level](obj);
104 }
105
106 void *xbt_lib_get_or_null(xbt_lib_t lib, const char *key, int level)
107 {
108   void **elts = xbt_dict_get_or_null(lib->dict, key);
109   return elts ? elts[level] : NULL;
110 }
111
112 xbt_dictelm_t xbt_lib_get_elm_or_null(xbt_lib_t lib, const char *key)
113 {
114   return xbt_dict_get_elm_or_null(lib->dict, key);
115 }
116
117 void *xbt_lib_get_level(xbt_dictelm_t elm, int level){
118   void **elts = elm->content;
119   return elts ? elts[level] : NULL;
120 }
121
122 void xbt_lib_remove(xbt_lib_t lib, const char *key){
123   xbt_dict_remove(lib->dict, key);
124 }