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