]> git.ipfire.org Git - thirdparty/bacula.git/commitdiff
Add copy operator to smartalist.
authorRadosław Korzeniewski <radoslaw@korzeniewski.net>
Thu, 14 Oct 2021 15:26:31 +0000 (17:26 +0200)
committerEric Bollengier <eric@baculasystems.com>
Thu, 14 Sep 2023 11:56:56 +0000 (13:56 +0200)
bacula/src/plugins/fd/pluginlib/smartalist.h
bacula/src/plugins/fd/pluginlib/smartalist_test.cpp

index 0b11bc6adb163ae1b5378a89e2dd8234d2b96b75..0326be4c5436bd852d8bfb8164483e49614252af 100644 (file)
 #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;
    }
 };
 
index c540cf06c73c1bff31f0f6b1e50d4a61033f21ad..d590ab8147253fed112ff59b057e80b7a753b811 100644 (file)
 #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");
@@ -50,7 +58,7 @@ int main()
 
    {
       smart_alist<testclass> list;
-      ti = new testclass;
+      ti = New(testclass);
       list.append(ti);
       ok(referencenumber == 1, "check first insert");
    }
@@ -64,7 +72,7 @@ int main()
       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");
@@ -72,6 +80,36 @@ int main()
 
    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();
 }