2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2017 Kern Sibbald
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.
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.
14 This notice must be preserved when any source code is
15 conveyed and/or propagated.
17 Bacula(R) is a registered trademark of Kern Sibbald.
20 * Bacula array list routines
22 * alist is a simple malloc'ed array of pointers. For the moment,
23 * it simply malloc's a bigger array controlled by num_grow.
24 * Default is to realloc the pointer array for each new member.
26 * Note: the list can have holes (empty items). This is done by
27 * using get() and put(). If you are using this kind of indexed
28 * list, you cannot use: prepend() and remove() as they will
29 * reorder the list. So, in the ilist array, these functions are
30 * disabled and the put method is defined.
32 * Kern Sibbald, June MMIII
39 * Private grow list function. Used to insure that
40 * at least one more "slot" is available.
42 void baselist::grow_list()
47 /* put() can insert and item anywhere in the list so
48 it's important to allocate at least last_item+1 items */
49 int min_grow = MAX(10, last_item+1);
50 if (num_grow < min_grow) {
51 num_grow = min_grow; /* default if not initialized */
55 items = (void **)malloc(num_grow * sizeof(void *));
56 for (i=0; i<num_grow; i++) {
60 } else if (last_item >= max_items) {
61 new_max_items = last_item + num_grow;
62 items = (void **)realloc(items, new_max_items * sizeof(void *));
63 for (i=max_items; i<new_max_items; i++) {
66 max_items = new_max_items;
86 return items[last_item-1];
92 if (cur_item >= last_item) {
95 return items[cur_item++];
104 return items[--cur_item];
109 * prepend an item to the list -- i.e. add to beginning
111 void alist::prepend(void *item)
114 if (num_items == 0) {
115 items[num_items++] = item;
116 if (num_items > last_item) {
117 last_item = num_items;
121 for (int i=last_item; i > 0; i--) {
122 items[i] = items[i-1];
131 * Append an item to the list
133 void baselist::append(void *item)
136 items[last_item++] = item;
141 * Put an item at a particular index
143 void ilist::put(int index, void *item)
145 if (index > last_item) {
149 if (items[index] == NULL) {
157 * Remove an item from the list
158 * Note: you must free the item when
159 * you are done with it.
161 void * baselist::remove_item(int index)
164 if (index < 0 || index >= last_item) {
169 /* last_item is from 1..n, we work from 0..n-1 */
170 for (int i=index; i < (last_item-1); i++) {
171 items[i] = items[i+1];
174 items[last_item-1] = NULL; /* The last item is shifted by one, the last slot is always free */
176 last_item--; /* We have shifted all items by 1 */
177 num_items--; /* We have 1 item less */
183 /* Get the index item -- we should probably allow real indexing here */
184 void * baselist::get(int index)
186 if (items == NULL || index < 0 || index > last_item) {
192 /* Destroy the list and its contents */
193 void baselist::destroy()
197 for (int i=0; i<max_items; i++) {
227 fileset = (FILESET *)malloc(sizeof(FILESET));
228 bmemzero(fileset, sizeof(FILESET));
229 fileset->mylist.init();
231 printf("Manual allocation/destruction of list:\n");
233 for (int i=0; i<20; i++) {
234 sprintf(buf, "This is item %d", i);
235 fileset->mylist.append(bstrdup(buf));
237 for (int i=0; i< fileset->mylist.size(); i++) {
238 printf("Item %d = %s\n", i, (char *)fileset->mylist[i]);
240 fileset->mylist.destroy();
243 printf("Allocation/destruction using new delete\n");
244 mlist = New(alist(50));
246 for (int i=0; i<20; i++) {
247 sprintf(buf, "This is item %d", i);
248 mlist->append(bstrdup(buf));
250 for (int i=0; i< mlist->size(); i++) {
251 printf("Item %d = %s\n", i, (char *)mlist->get(i));
253 printf("\nIndexed test. Insert 210 items.\n");
254 /* Test indexed list */
259 printf("Test remove()\n");
262 alist *alst = New(alist(10, owned_by_alist));
263 alst->append(bstrdup("trash"));
264 alst->append(bstrdup("0"));
265 alst->append(bstrdup("1"));
266 alst->append(bstrdup("2"));
267 alst->append(bstrdup("3"));
268 free(alst->remove(0));
269 foreach_alist(elt, alst) {
272 printf("%d %s\n", i++, elt);
280 alist *alst = New(alist(10, owned_by_alist));
281 alst->append(bstrdup("0"));
282 alst->append(bstrdup("1"));
283 alst->append(bstrdup("2"));
284 alst->append(bstrdup("trash"));
285 alst->append(bstrdup("3"));
286 free(alst->remove(3));
287 foreach_alist(elt, alst) {
290 printf("%d %s\n", i++, elt);
298 alist *alst = New(alist(10, owned_by_alist));
299 alst->append(bstrdup("0"));
300 alst->append(bstrdup("1"));
301 alst->append(bstrdup("2"));
302 alst->append(bstrdup("3"));
303 alst->append(bstrdup("trash"));
304 free(alst->remove(4));
305 foreach_alist(elt, alst) {
308 printf("%d %s\n", i++, elt);
316 alist *alst = New(alist(10, owned_by_alist));
317 alst->append(bstrdup("0"));
318 alst->append(bstrdup("1"));
319 alst->append(bstrdup("2"));
320 alst->append(bstrdup("3"));
321 alst->append(bstrdup("4"));
322 ASSERT(alst->remove(5) == NULL);
323 foreach_alist(elt, alst) {
326 printf("%d %s\n", i++, elt);
332 printf("Test pop()\n");
335 alist *alst = New(alist(10, owned_by_alist));
336 alst->append(bstrdup("0"));
337 alst->append(bstrdup("1"));
338 alst->append(bstrdup("2"));
339 alst->append(bstrdup("3"));
340 alst->append(bstrdup("trash"));
341 ASSERT(alst->last_index() == 5);
343 ASSERT(alst->last_index() == 4);
344 foreach_alist(elt, alst) {
347 printf("%d %s\n", i++, elt);
352 ilist *ilst = New(ilist(10, owned_by_alist));
353 sprintf(buf, "This is item 10");
354 ilst->put(10, bstrdup(buf));
355 printf("ilst size is %d. last_item=%d. max_items=%d\n",
356 ilst->size(), ilst->last_index(), ilst->max_size());
357 ASSERT(ilst->size() == 1);
362 ilist *ilst = New(ilist(10, not_owned_by_alist));
363 ilst->put(15, (char *)"something");
364 printf("ilst size is %d. last_item=%d. max_items=%d\n",
365 ilst->size(), ilst->last_index(), ilst->max_size());
366 ASSERT(ilst->size() == 1);
367 ASSERT(ilst->last_index() == 15);
371 ilist *ilst = New(ilist(50));
372 for (int i=0; i<115; i++) {
373 sprintf(buf, "This is item %d", i);
374 ilst->put(i, bstrdup(buf));
377 printf("ilst size is %d. last_item=%d. max_items=%d\n",
378 ilst->size(), ilst->last_index(), ilst->max_size());
379 for (int i=0; i< ilst->size(); i++) {
380 printf("Item %d = %s\n", i, (char *)ilst->get(i));
385 printf("Test alist push().\n");
386 mlist = New(alist(10));
388 printf("mlist size is %d. last_item=%d. max_items=%d\n",
389 mlist->size(), mlist->last_index(), mlist->max_size());
390 for (int i=0; i<20; i++) {
391 sprintf(buf, "This is item %d", i);
392 mlist->push(bstrdup(buf));
393 printf("mlist size is %d. last_item=%d. max_items=%d\n",
394 mlist->size(), mlist->last_index(), mlist->max_size());
396 printf("Test alist pop()\n");
397 for (int i=0; (bp=(char *)mlist->pop()); i++) {
398 printf("Item %d = %s\n", i, bp);
401 printf("mlist size is %d. last_item=%d. max_items=%d\n",
402 mlist->size(), mlist->last_index(), mlist->max_size());
404 for (int i=0; i<mlist->max_size(); i++) {
405 bp = (char *) mlist->get(i);
407 printf("Big problem. Item %d item=%p, but should be NULL\n", i, bp);
410 printf("Done push() pop() tests\n");
414 ilst = New(ilist(10, not_owned_by_alist));
416 ilst->append((void*)1);
421 ilist a(4, not_owned_by_alist);
422 a.append((void*)"test1");
424 ilist b(4, not_owned_by_alist);
425 bmemzero(&b, sizeof b);
426 b.append((void*)"test1");
428 sm_dump(false); /* test program */