]> git.lizzy.rs Git - nothing.git/blob - src/system/lt.h
Remove Grid and ActionPicker
[nothing.git] / src / system / lt.h
1 #ifndef LT_H_
2 #define LT_H_
3
4 #include <assert.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include "system/stacktrace.h"
8
9 #define LT_INITIAL_CAPACITY 8
10
11 typedef void (*Dtor)(void*);
12
13 typedef struct {
14     void *res;
15     Dtor dtor;
16 } Slot;
17
18 typedef struct {
19     Slot *slots_end;
20     size_t capacity;
21     Slot *slots;
22 } Lt;
23
24 static inline Lt *create_lt(void)
25 {
26     return calloc(1, sizeof(Lt));
27 }
28
29 static inline void destroy_lt(Lt *lt)
30 {
31     trace_assert(lt);
32
33     if (lt->slots_end) {
34         for (Slot *p = lt->slots_end - 1; p >= lt->slots; --p) {
35             if (p->res) {
36                 p->dtor(p->res);
37             }
38         }
39     }
40
41     if (lt->slots) {
42         free(lt->slots);
43     }
44
45     free(lt);
46 }
47
48 #define PUSH_LT(lt, res, dtor)                  \
49     lt_push(lt, (void*)res, (Dtor)dtor)
50
51 static inline void *lt_push(Lt *lt, void *res, Dtor dtor)
52 {
53     trace_assert(lt);
54     size_t size = (size_t)(lt->slots_end - lt->slots);
55     if (size >= lt->capacity) {
56         if (lt->capacity == 0) {
57             lt->capacity = LT_INITIAL_CAPACITY;
58             lt->slots = calloc(LT_INITIAL_CAPACITY, sizeof(Slot));
59             lt->slots_end = lt->slots;
60         } else {
61             lt->capacity *= 2;
62             lt->slots = realloc(lt->slots, lt->capacity * sizeof(Slot));
63             lt->slots_end = lt->slots + size;
64         }
65     }
66
67     lt->slots_end->res = res;
68     lt->slots_end->dtor = dtor;
69     lt->slots_end++;
70
71     return res;
72 }
73
74 #define RETURN_LT(lt, result)                   \
75     return (destroy_lt(lt), result)
76
77 #define RETURN_LT0(lt)                          \
78     do {                                        \
79         destroy_lt(lt);                         \
80         return;                                 \
81     } while (0)
82
83 #define RESET_LT(lt, old_res, new_res)          \
84     lt_reset(lt, (void*) old_res, (void*) new_res)
85
86 static inline void *lt_reset(Lt *lt, void *old_res, void *new_res)
87 {
88     trace_assert(lt);
89     trace_assert(old_res != new_res);
90
91     for(Slot *p = lt->slots; p < lt->slots_end; ++p) {
92         if (p->res == old_res) {
93             p->dtor(old_res);
94             p->res = new_res;
95             return new_res;
96         }
97     }
98
99     trace_assert(0 && "Resource was not found");
100     return NULL;
101 }
102
103
104 #define REPLACE_LT(lt, old_res, new_res)        \
105     lt_replace(lt, (void *)old_res, (void*)new_res)
106
107 static inline void *lt_replace(Lt *lt, void *old_res, void *new_res)
108 {
109     trace_assert(lt);
110     for(Slot *p = lt->slots; p < lt->slots_end; ++p) {
111         if (p->res == old_res) {
112             p->res = new_res;
113             return new_res;
114         }
115     }
116
117     trace_assert(0 && "Resource was not found");
118     return NULL;
119 }
120
121 #define RELEASE_LT(lt, res)                     \
122     lt_release(lt, (void*)res)
123
124 static inline void *lt_release(Lt *lt, void *res)
125 {
126     trace_assert(lt);
127     for(Slot *p = lt->slots; p < lt->slots_end; ++p) {
128         if (p->res == res) {
129             memmove(p, p + 1, (size_t)(lt->slots_end - p - 1) * sizeof(Slot));
130             lt->slots_end--;
131             return res;
132         }
133     }
134
135     trace_assert(0 && "Resource was not found");
136     return NULL;
137 }
138
139 #endif  // LT_H_