1 /*
2 Bacula(R) - The Network Backup Solution
3
4 Copyright (C) 2000-2020 Kern Sibbald
5
6 The original author of Bacula is Kern Sibbald, with contributions
7 from many others, a complete list can be found in the file AUTHORS.
8
9 You may use this file and others of this release according to the
10 license defined in the LICENSE file, which includes the Affero General
11 Public License, v3.0 ("AGPLv3") and some additional permissions and
12 terms pursuant to its AGPLv3 Section 7.
13
14 This notice must be preserved when any source code is
15 conveyed and/or propagated.
16
17 Bacula(R) is a registered trademark of Kern Sibbald.
18 */
19 /*
20 * Kern Sibbald, June MMIII
21 */
22
23 #ifndef ALIST_H
24 #define ALIST_H
25
26 extern bool is_null(const void *ptr);
27
28 /*
29 * There is a lot of extra casting here to work around the fact
30 * that some compilers (Sun and Visual C++) do not accept
31 * (void *) as an lvalue on the left side of an equal.
32 *
33 * Loop var through each member of list
34 */
35 #ifdef HAVE_TYPEOF
36 #define foreach_alist(var, list) \
37 for((var)=(typeof(var))(list)->first(); (var); (var)=(typeof(var))(list)->next() )
38 #else
39 #define foreach_alist(var, list) \
40 for((*((void **)&(var))=(void*)((list)->first())); \
41 (var); \
42 (*((void **)&(var))=(void*)((list)->next())))
43 #endif
44
45 #ifdef HAVE_TYPEOF
46 #define foreach_alist_index(inx, var, list) \
47 for(inx=0; ((var)=(typeof(var))(list)->get(inx)); inx++ )
48 #else
49 #define foreach_alist_index(inx, var, list) \
50 for(inx=0; ((*((void **)&(var))=(void*)((list)->get(inx)))); inx++ )
51 #endif
52
53
54
55
56 /* Second arg of init */
57 enum {
58 owned_by_alist = true,
59 not_owned_by_alist = false
60 };
61
62 /*
63 * Array list -- much like a simplified STL vector
64 * array of pointers to inserted items. baselist is
65 * the common code between alist and ilist
66 */
67 class baselist : public SMARTALLOC {
68 protected:
69 void **items; /* from 0..n-1 */
70 int num_items; /* from 1..n */
71
72 int last_item; /* maximum item index (1..n). */
73
74 int max_items; /* maximum possible items (array size) (1..n) */
75 int num_grow;
76 int cur_item; /* from 1..n */
77 bool own_items;
78 void grow_list(void);
79 void *remove_item(int index);
80 public:
81 baselist(int num = 100, bool own=true);
82 ~baselist();
83 void init(int num = 100, bool own=true);
84 void append(void *item);
85 void *get(int index);
86 bool empty() const;
last_index()87 int last_index() const { return last_item; };
max_size()88 int max_size() const { return max_items; };
89 void * operator [](int index) const;
current()90 int current() const { return cur_item; };
91 int size() const;
92 void destroy();
93 void grow(int num);
94
95 /* Use it as a stack, pushing and poping from the end */
push(void * item)96 void push(void *item) { append(item); };
pop()97 void *pop() { return remove_item(num_items-1); };
98 };
99
100 class alist: public baselist
101 {
102 public:
baselist(num,own)103 alist(int num = 100, bool own=true): baselist(num, own) {};
104 void *prev();
105 void *next();
106 void *last();
107 void *first();
108 void prepend(void *item);
remove(int index)109 void *remove(int index) { return remove_item(index);};
110 };
111
112 /*
113 * Define index operator []
114 */
115 inline void * baselist::operator [](int index) const {
116 if (index < 0 || index >= max_items) {
117 return NULL;
118 }
119 return items[index];
120 }
121
empty()122 inline bool baselist::empty() const
123 {
124 return num_items == 0;
125 }
126
127 /*
128 * This allows us to do explicit initialization,
129 * allowing us to mix C++ classes inside malloc'ed
130 * C structures. Define before called in constructor.
131 */
init(int num,bool own)132 inline void baselist::init(int num, bool own)
133 {
134 items = NULL;
135 num_items = 0;
136 last_item = 0;
137 max_items = 0;
138 num_grow = num;
139 own_items = own;
140 }
141
142 /* Constructor */
baselist(int num,bool own)143 inline baselist::baselist(int num, bool own)
144 {
145 init(num, own);
146 }
147
148 /* Destructor */
~baselist()149 inline baselist::~baselist()
150 {
151 destroy();
152 }
153
154 /* Current size of list */
size()155 inline int baselist::size() const
156 {
157 if (is_null(this)) return 0;
158 return num_items;
159 }
160
161 /* How much to grow by each time */
grow(int num)162 inline void baselist::grow(int num)
163 {
164 num_grow = num;
165 }
166
167 #endif // ALIST_H
168