#ifndef _SMARTALIST_H_
#define _SMARTALIST_H_
+// This is for custom alist iterator
+// which is not working as Bacula can't use any of the modern C++ headers (yet?)
+// #if __cplusplus >= 201104
+// #include <iterator> // For std::forward_iterator_tag
+// #include <cstddef> // For std::ptrdiff_t
+// #endif
/**
* @brief This is a simple smart array list (alist) resource guard conceptually based on C++11 - RAII.
template <typename T>
class smart_alist : public alist
{
+private:
+ void _destroy(bool _remove_items = true)
+ {
+ if (items)
+ {
+ for (int i = 0; i < max_items; i++)
+ {
+ if (items[i])
+ {
+ T *item = (T*)items[i];
+ items[i] = NULL;
+ delete item;
+ }
+ }
+ if (_remove_items)
+ {
+ free(items);
+ items = NULL;
+ }
+ }
+ num_items = 0;
+ last_item = 0;
+ max_items = 0;
+ }
+
public:
+ // This is a custom alist iteration for modern C++
+ // #if __cplusplus >= 201104
+ // struct Iterator
+ // {
+ // using iterator_category = std::forward_iterator_tag;
+ // using difference_type = std::ptrdiff_t;
+ // using value_type = T;
+ // using pointer = T*; // or also value_type*
+ // using reference = T&; // or also value_type&
+
+ // private:
+ // pointer m_ptr;
+
+ // public:
+ // Iterator(pointer ptr) : m_ptr(ptr) {}
+ // reference operator*() const { return *m_ptr; }
+ // pointer operator->() { return m_ptr; }
+
+ // // Prefix increment
+ // Iterator& operator++() { m_ptr++; return *this; }
+
+ // // Postfix increment
+ // Iterator operator++(int) { Iterator tmp = *this; ++(*this); return tmp; }
+
+ // friend bool operator== (const Iterator& a, const Iterator& b) { return a.m_ptr == b.m_ptr; };
+ // friend bool operator!= (const Iterator& a, const Iterator& b) { return a.m_ptr != b.m_ptr; };
+ // };
+
+ // // our iterator interface
+ // inline Iterator begin() { return Iterator(&items[0]); }
+ // inline Iterator end() { return Iterator(NULL); }
+ // #endif
+
smart_alist(int num = 10) : alist(num, not_owned_by_alist) {}
- ~smart_alist()
+ ~smart_alist() { _destroy(); }
+
+ // This is a simple copy operator
+ // it requires a T(T*) constructor to work correctly
+ inline smart_alist<T> &operator=(const smart_alist<T> &other)
{
- T * it;
- if (items) {
- for (int i = 0; i < max_items; i++) {
- if (items[i]) {
- it = (T*)items[i];
- items[i] = NULL;
- delete it;
+ if (items != other.items)
+ {
+ _destroy(false);
+ if (other.items)
+ {
+ for (int i = 0; i < other.max_items; i++)
+ {
+ if (other.items[i])
+ {
+ T *item = New(T((const T*)other.items[i]));
+ this->append(item);
+ }
}
}
}
+ return *this;
+ }
+ // This is a simple move operator
+ inline smart_alist<T> &operator=(smart_alist<T> &&other)
+ {
+ if (items != other.items)
+ {
+ _destroy();
+ items = other.items;
+ other.init(other.num_grow, own_items);
+ }
+ return *this;
}
};
#include "pluginlib.h"
#include "smartalist.h"
#include "unittests.h"
+#include <utility>
bFuncs *bfuncs;
bInfo *binfo;
static int referencenumber = 0;
-struct testclass
+struct testclass : public SMARTALLOC
{
testclass() { referencenumber++; };
~testclass() { referencenumber--; };
};
+struct testvalue : public SMARTALLOC
+{
+ int value;
+ testvalue(const testvalue *other) { value = other->value; }
+ testvalue() : value(0) {}
+};
+
int main()
{
Unittests pluglib_test("smartalist_test");
{
smart_alist<testclass> list;
- ti = new testclass;
+ ti = New(testclass);
list.append(ti);
ok(referencenumber == 1, "check first insert");
}
smart_alist<testclass> list;
for (int a = 0; a < refs; a++)
{
- ti = new testclass;
+ ti = New(testclass);
list.append(ti);
}
ok(referencenumber == refs, "check bulk inserts");
ok(referencenumber == 0, "check smart free");
+ {
+ smart_alist<testvalue> list;
+ testvalue *ti = New(testvalue);
+ ti->value = 0xfff1;
+ list.append(ti);
+
+ smart_alist<testvalue> copylist;
+
+ copylist = list;
+
+ testvalue *tv = (testvalue*)copylist.first();
+ rok(tv != NULL, "test first value");
+ ok(tv->value == ti->value, "test copy value");
+ ok(tv != ti, "test copy pointer");
+ }
+
+// #if __cplusplus >= 201104
+// {
+// smart_alist<testvalue> list;
+// // fill it with data
+// for (int i = 0; i < 10;i++)
+// {
+// testvalue *ti = New(testvalue);
+// ti->value = 100 + i;
+// list.append(ti);
+// }
+
+// ok(list.size() == 10, "test prefill data size");
+// }
+// #endif
return report();
}