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