Line data Source code
1 1 : /**
2 : * Copyright (C) 2008-2018 HPDCS Group
3 : * http://www.dis.uniroma1.it/~hpdcs
4 : *
5 : *
6 : * This file is part of ROOT-Sim (ROme OpTimistic Simulator).
7 : *
8 : * ROOT-Sim is free software; you can redistribute it and/or modify it under the
9 : * terms of the GNU General Public License as published by the Free Software
10 : * Foundation; only version 3 of the License applies.
11 : *
12 : * ROOT-Sim is distributed in the hope that it will be useful, but WITHOUT ANY
13 : * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14 : * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15 : *
16 : * You should have received a copy of the GNU General Public License along with
17 : * ROOT-Sim; if not, write to the Free Software Foundation, Inc.,
18 : * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 : *
20 : * @file array.h
21 : * @brief This is the implementation of a dynamic array, used for managing various data structures
22 : * @author Andrea Piccione
23 : * @date 18 June 2018
24 : */
25 :
26 : #ifndef ARRAY_H_
27 : #define ARRAY_H_
28 :
29 : #include <mm/dymelor.h>
30 :
31 : #include <memory.h>
32 :
33 : // TODO: add some type checking and size checking (is it necessary?)
34 :
35 0 : #define INIT_SIZE_ARRAY 8U
36 :
37 0 : #define rootsim_array(type) \
38 : struct { \
39 : type *items; \
40 : unsigned count, capacity; \
41 : }
42 :
43 : // you can use the array to directly index items, but do at your risk and peril
44 0 : #define array_items(self) ((self).items)
45 :
46 0 : #define array_count(self) ((self).count)
47 :
48 0 : #define array_capacity(self) ((self).capacity)
49 :
50 0 : #define array_shrink(self) ({ \
51 : if (array_count(self) > INIT_SIZE_ARRAY && array_count(self) * 3 <= array_capacity(self)) { \
52 : array_capacity(self) /= 2; \
53 : array_items(self) = rsrealloc(array_items(self), array_capacity(self) * sizeof(*array_items(self))); \
54 : } \
55 : })
56 :
57 0 : #define array_expand(self) ({ \
58 : if(array_count(self) >= array_capacity(self)){\
59 : array_capacity(self) *= 2; \
60 : array_items(self) = rsrealloc(array_items(self), array_capacity(self) * sizeof(*array_items(self))); \
61 : } \
62 : })
63 :
64 0 : #define array_new(type) ({ \
65 : rootsim_array(type) *__newarr; \
66 : __newarr = rsalloc(sizeof(*__newarr)); \
67 : array_init(*__newarr);\
68 : __newarr; \
69 : })
70 :
71 0 : #define array_free(self) ({ \
72 : rsfree(array_items(self)); \
73 : rsfree(&(self)); \
74 : })
75 :
76 0 : #define array_init(self) ({ \
77 : array_capacity(self) = INIT_SIZE_ARRAY; \
78 : array_items(self) = rsalloc(array_capacity(self) * sizeof(*array_items(self))); \
79 : array_count(self) = 0; \
80 : })
81 :
82 0 : #define array_fini(self) ({ \
83 : rsfree(array_items(self)); \
84 : })
85 : //fixme array_expand doesn't work when reserving with count high since it only doubles once
86 0 : #define array_reserve(self, count) ({ \
87 : __typeof__(array_count(self)) __rsvidx = array_count(self); \
88 : array_count(self) += (count); \
89 : array_expand(self); \
90 : &(array_items(self)[__rsvidx]); \
91 : })
92 :
93 0 : #define array_push(self, elem) ({ \
94 : array_expand(self); \
95 : array_items(self)[array_count(self)] = (elem); \
96 : array_count(self)++; \
97 : })
98 :
99 0 : #define array_pop(self) ({ \
100 : if(unlikely(!array_count(self))) \
101 : rootsim_error(true, "pop of an empty array"); \
102 : __typeof__(*array_items(self)) __popval; \
103 : array_count(self)--; \
104 : __popval = array_items(self)[array_count(self)]; \
105 : array_shrink(self); \
106 : __popval; \
107 : })
108 :
109 0 : #define array_add_at(self, i, elem) ({ \
110 : if(unlikely(array_count(self) <= (i))) \
111 : rootsim_error(true, "out of bound add in a dynamic array"); \
112 : array_expand(self); \
113 : memmove(&(array_items(self)[(i)+1]), &(array_items(self)[(i)]), sizeof(*array_items(self)) * (array_count(self)-(i))); \
114 : array_items(self)[(i)] = (elem); \
115 : array_count(self)++; \
116 : })
117 :
118 0 : #define array_lazy_remove_at(self, i) ({ \
119 : if(unlikely(array_count(self) <= (i))) \
120 : rootsim_error(true, "out of bound removal in a dynamic array"); \
121 : __typeof__(*array_items(self)) __rmval; \
122 : array_count(self)--; \
123 : __rmval = array_items(self)[(i)]; \
124 : array_items(self)[(i)] = array_items(self)[array_count(self)]; \
125 : array_shrink(self); \
126 : __rmval; \
127 : })
128 :
129 0 : #define array_remove_at(self, i) ({ \
130 : if(unlikely(array_count(self) <= (i))) \
131 : rootsim_error(true, "out of bound removal in a dynamic array"); \
132 : __typeof__(*array_items(self)) __rmval; \
133 : array_count(self)--; \
134 : __rmval = array_items(self)[(i)]; \
135 : memmove(&(array_items(self)[(i)]), &(array_items(self)[(i)+1]), sizeof(*array_items(self)) * (array_count(self)-(i))); \
136 : array_shrink(self); \
137 : __rmval; \
138 : })
139 :
140 0 : #define array_remove(self, elem) ({ \
141 : typeof(array_count(self)) __cntr = array_count(self); \
142 : while(__cntr--){ \
143 : if(array_items(self)[__cntr] == (elem)){\
144 : array_remove_at(self, __cntr); \
145 : break; \
146 : } \
147 : } \
148 : })
149 : //this isn't checked CARE! TODO add checking
150 0 : #define array_peek(self) (array_items(self)[array_count(self)-1])
151 : //this isn't checked CARE! TODO add checking
152 0 : #define array_get_at(self, i) (array_items(self)[i])
153 :
154 0 : #define array_empty(self) (array_count(self) == 0)
155 :
156 0 : #define array_dump_size(self) ({ \
157 : sizeof(array_count(self)) + array_count(self)*sizeof(*array_items(self)); \
158 : })
159 :
160 0 : #define array_dump(self, mem_area) ({ \
161 : memcpy((mem_area), &array_count(self), sizeof(array_count(self))); \
162 : (mem_area) = ((unsigned char *)(mem_area)) + sizeof(array_count(self)); \
163 : memcpy((mem_area), array_items(self), array_count(self) * sizeof(*array_items(self))); \
164 : mem_area = ((unsigned char *)(mem_area)) + array_count(self) * sizeof(*array_items(self)); \
165 : })
166 :
167 0 : #define array_load(self, mem_area) ({ \
168 : memcpy(&array_count(self), (mem_area), sizeof(array_count(self))); \
169 : (mem_area) = ((unsigned char *)(mem_area)) + sizeof(array_count(self)); \
170 : array_capacity(self) = max(array_count(self), INIT_SIZE_ARRAY); \
171 : array_items(self) = rsalloc(array_capacity(self) * sizeof(*array_items(self))); \
172 : memcpy(array_items(self), (mem_area), array_count(self) * sizeof(*array_items(self))); \
173 : (mem_area) = ((unsigned char *)(mem_area)) + (array_count(self) * sizeof(*array_items(self))); \
174 : })
175 :
176 : #endif /* ARRAY_H_ */
|