1 /*
2 BAREOS® - Backup Archiving REcovery Open Sourced
3
4 Copyright (C) 2003-2012 Free Software Foundation Europe e.V.
5 Copyright (C) 2016-2019 Bareos GmbH & Co. KG
6
7 This program is Free Software; you can redistribute it and/or
8 modify it under the terms of version three of the GNU Affero General Public
9 License as published by the Free Software Foundation and included
10 in the file LICENSE.
11
12 This program is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Affero General Public License for more details.
16
17 You should have received a copy of the GNU Affero General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 02110-1301, USA.
21 */
22 /*
23 * Kern Sibbald, June MMIII
24 */
25 /**
26 * @file
27 * alist header file
28 */
29 #ifndef BAREOS_LIB_ALIST_H_
30 #define BAREOS_LIB_ALIST_H_
31
32
33 /**
34 * There is a lot of extra casting here to work around the fact
35 * that some compilers (Sun and Visual C++) do not accept
36 * (void *) as an lvalue on the left side of an equal.
37 *
38 * Loop var through each member of list
39 * Loop var through each member of list using an increasing index.
40 * Loop var through each member of list using an decreasing index.
41 */
42 #ifdef HAVE_TYPEOF
43 #define foreach_alist(var, list) \
44 for ((var) = list ? (typeof((var)))(list)->first() : 0; (var); \
45 (var) = (typeof(var))(list)->next())
46
47 #define foreach_alist_null(var, list) \
48 for ((var) = list ? (typeof((var)))(list)->first() : NULL; (var); \
49 (var) = (typeof(var))(list)->next())
50
51 #define foreach_alist_index(inx, var, list) \
52 for ((inx) = 0; \
53 (list != NULL) ? ((var) = (typeof((var)))(list)->get((inx))) : 0; \
54 (inx)++)
55
56 #define foreach_alist_rindex(inx, var, list) \
57 for ((list != NULL) ? (inx) = ((list)->size() - 1) : 0; \
58 (list != NULL) ? ((var) = (typeof((var)))(list)->get((inx))) : 0; \
59 (inx)--)
60
61 #else
62 #define foreach_alist(var, list) \
63 for (list ? (*((void**)&(var)) = (void*)((list)->first())) : 0; (var); \
64 (*((void**)&(var)) = (void*)((list)->next())))
65
66 #define foreach_alist_null(var, list) \
67 for (list ? (*((void**)&(var)) = (void*)((list)->first())) : NULL; (var); \
68 (*((void**)&(var)) = (void*)((list)->next())))
69
70 #define foreach_alist_index(inx, var, list) \
71 for ((inx) = 0; \
72 (list != NULL) ? ((*((void**)&(var)) = (void*)((list)->get((inx))))) \
73 : 0; \
74 (inx)++)
75
76 #define foreach_alist_rindex(inx, var, list) \
77 for ((list != NULL) ? (inx) = ((list)->size() - 1) : 0; \
78 (list != NULL) ? ((*((void**)&(var)) = (void*)((list)->get((inx))))) \
79 : 0; \
80 (inx)--)
81 #endif
82
83 /**
84 * Second arg of init
85 */
86 enum
87 {
88 owned_by_alist = true,
89 not_owned_by_alist = false
90 };
91
92 /**
93 * Array list -- much like a simplified STL vector
94 * array of pointers to inserted items
95 */
96 class alist {
97 void** items = nullptr;
98 int num_items = 0;
99 int max_items = 0;
100 int num_grow = 0;
101 int cur_item = 0;
102 bool own_items = false;
103 void GrowList(void);
104
105 public:
106 alist(int num = 1, bool own = true);
107 ~alist();
108 void init(int num = 1, bool own = true);
109 void append(void* item);
110 void prepend(void* item);
111 void* remove(int index);
112 void* get(int index);
113 bool empty() const;
114 void* prev();
115 void* next();
116 void* first();
117 void* last();
118 void* operator[](int index) const;
current()119 int current() const { return cur_item; }
120 int size() const;
121 void destroy();
122 void grow(int num);
123
124 /*
125 * Use it as a stack, pushing and poping from the end
126 */
push(void * item)127 void push(void* item) { append(item); }
pop()128 void* pop() { return remove(num_items - 1); }
129 };
130
131 /**
132 * Define index operator []
133 */
134 inline void* alist::operator[](int index) const
135 {
136 if (index < 0 || index >= num_items) { return NULL; }
137 return items[index];
138 }
139
empty()140 inline bool alist::empty() const { return num_items == 0; }
141
142 /**
143 * This allows us to do explicit initialization,
144 * allowing us to mix C++ classes inside malloc'ed
145 * C structures. Define before called in constructor.
146 */
init(int num,bool own)147 inline void alist::init(int num, bool own)
148 {
149 items = nullptr;
150 num_items = 0;
151 max_items = 0;
152 num_grow = num;
153 own_items = own;
154 cur_item = 0;
155 }
156
157 /* Constructor */
alist(int num,bool own)158 inline alist::alist(int num, bool own) { init(num, own); }
159
160 /* Destructor */
~alist()161 inline alist::~alist() { destroy(); }
162
163
164 /* Current size of list */
size()165 inline int alist::size() const
166 {
167 /*
168 * Check for null pointer, which allows test
169 * on size to succeed even if nothing put in
170 * alist.
171 */
172 return num_items;
173 }
174
175 /* How much to grow by each time */
grow(int num)176 inline void alist::grow(int num) { num_grow = num; }
177
178 #endif /* BAREOS_LIB_ALIST_H_ */
179