[beast: 15/20] BSE: add and use DataListContainer from Rapicorn
- From: Tim Janik <timj src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [beast: 15/20] BSE: add and use DataListContainer from Rapicorn
- Date: Sun, 24 Sep 2017 00:20:54 +0000 (UTC)
commit 91f03191160873b4a5d9e2f75f05be921fd20881
Author: Tim Janik <timj gnu org>
Date: Sun Sep 17 14:39:04 2017 +0200
BSE: add and use DataListContainer from Rapicorn
Import is based on Rapicorn commit id:
bf228016cba3f6d252ee2cc38e1ed32607f37bf0
Signed-off-by: Tim Janik <timj gnu org>
bse/bseobject.hh | 3 +-
sfi/Makefile.am | 2 +
sfi/bcore.hh | 2 -
sfi/datalist.cc | 67 +++++++++++++++++++++++++
sfi/datalist.hh | 145 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 216 insertions(+), 3 deletions(-)
---
diff --git a/bse/bseobject.hh b/bse/bseobject.hh
index 3bf1035..c6b2e27 100644
--- a/bse/bseobject.hh
+++ b/bse/bseobject.hh
@@ -2,7 +2,8 @@
#ifndef __BSE_OBJECT_H__
#define __BSE_OBJECT_H__
-#include <bse/bseparam.hh>
+#include <bse/bseparam.hh>
+#include <sfi/datalist.hh>
namespace Bse {
diff --git a/sfi/Makefile.am b/sfi/Makefile.am
index 1b86be0..28a172c 100644
--- a/sfi/Makefile.am
+++ b/sfi/Makefile.am
@@ -17,6 +17,7 @@ sfi_public_headers = $(strip \
sficxx.hh sfiring.hh sfimemory.hh sficomport.hh \
sfi.hh \
gbsearcharray.hh \
+ datalist.hh \
entropy.hh \
randomhash.hh \
testing.hh \
@@ -30,6 +31,7 @@ sfi_all_sources = $(strip \
sfitime.cc sfitypes.cc sfivalues.cc \
sfivisitors.cc sfiustore.cc \
sfiring.cc sfimemory.cc sficomport.cc \
+ datalist.cc \
entropy.cc \
randomhash.cc \
testing.cc \
diff --git a/sfi/bcore.hh b/sfi/bcore.hh
index f15c5ed..63e2113 100644
--- a/sfi/bcore.hh
+++ b/sfi/bcore.hh
@@ -28,8 +28,6 @@ typedef vector<String> StringVector; ///< Convenience alias for a std::vector
using Aida::Any;
using Aida::EventFd;
using Rapicorn::url_show;
-using Rapicorn::DataKey;
-using Rapicorn::DataListContainer;
using Rapicorn::void_t;
using Rapicorn::Blob;
using Rapicorn::Res;
diff --git a/sfi/datalist.cc b/sfi/datalist.cc
new file mode 100644
index 0000000..9e03959
--- /dev/null
+++ b/sfi/datalist.cc
@@ -0,0 +1,67 @@
+// This Source Code Form is licensed MPL-2.0: http://mozilla.org/MPL/2.0
+#include "datalist.hh"
+
+namespace Bse {
+
+// == DataList ==
+DataList::NodeBase::~NodeBase ()
+{}
+
+void
+DataList::set_data (NodeBase *node)
+{
+ /* delete old node */
+ NodeBase *it = rip_data (node->key);
+ if (it)
+ delete it;
+ /* prepend node */
+ node->next = nodes;
+ nodes = node;
+}
+
+DataList::NodeBase*
+DataList::get_data (DataKey<void> *key) const
+{
+ NodeBase *it;
+ for (it = nodes; it; it = it->next)
+ if (it->key == key)
+ return it;
+ return NULL;
+}
+
+DataList::NodeBase*
+DataList::rip_data (DataKey<void> *key)
+{
+ NodeBase *last = NULL, *it;
+ for (it = nodes; it; last = it, it = last->next)
+ if (it->key == key)
+ {
+ /* unlink existing node */
+ if (last)
+ last->next = it->next;
+ else
+ nodes = it->next;
+ it->next = NULL;
+ return it;
+ }
+ return NULL;
+}
+
+void
+DataList::clear_like_destructor()
+{
+ while (nodes)
+ {
+ NodeBase *it = nodes;
+ nodes = it->next;
+ it->next = NULL;
+ delete it;
+ }
+}
+
+DataList::~DataList()
+{
+ clear_like_destructor();
+}
+
+} // Bse
diff --git a/sfi/datalist.hh b/sfi/datalist.hh
new file mode 100644
index 0000000..0c13f52
--- /dev/null
+++ b/sfi/datalist.hh
@@ -0,0 +1,145 @@
+// This Source Code Form is licensed MPL-2.0: http://mozilla.org/MPL/2.0
+#ifndef __BSE_DATALIST_HH__
+#define __BSE_DATALIST_HH__
+
+#include <sfi/bcore.hh>
+
+namespace Bse {
+
+// == DataList ==
+/// DataKey objects are used to identify and manage custom data members of DataListContainer objects.
+template<typename Type> class DataKey {
+private:
+ /*Copy*/ DataKey (const DataKey&);
+ DataKey& operator= (const DataKey&);
+public:
+ /* explicit */ DataKey () { }
+ virtual Type fallback () { Type d = Type(); return d; } ///< Return the default
value for Type.
+ virtual void destroy (Type data) { /* destruction hook */ } ///< Hook invoked when @a
data is deleted.
+ virtual ~DataKey () {}
+};
+
+/// Underlying storage implementation for a DataListContainer.
+class DataList {
+ class NodeBase {
+ protected:
+ NodeBase *next;
+ DataKey<void> *key;
+ explicit NodeBase (DataKey<void> *k) : next (NULL), key (k) {}
+ virtual ~NodeBase ();
+ friend class DataList;
+ };
+ template<typename T>
+ class Node : public NodeBase {
+ T data;
+ public:
+ T get_data () { return data; }
+ T swap (T d) { T result = data; data = d; return result; }
+ virtual ~Node()
+ {
+ if (key)
+ {
+ DataKey<T> *dkey = reinterpret_cast<DataKey<T>*> (key);
+ dkey->destroy (data);
+ }
+ }
+ explicit Node (DataKey<T> *k,
+ T d) :
+ NodeBase (reinterpret_cast<DataKey<void>*> (k)),
+ data (d)
+ {}
+ };
+ NodeBase *nodes;
+ BSE_CLASS_NON_COPYABLE (DataList);
+public:
+ DataList() :
+ nodes (NULL)
+ {}
+ template<typename T> void
+ set (DataKey<T> *key,
+ T data)
+ {
+ Node<T> *node = new Node<T> (key, data);
+ set_data (node);
+ }
+ template<typename T> T
+ get (DataKey<T> *key) const
+ {
+ NodeBase *nb = get_data (reinterpret_cast<DataKey<void>*> (key));
+ if (nb)
+ {
+ Node<T> *node = reinterpret_cast<Node<T>*> (nb);
+ return node->get_data();
+ }
+ else
+ return key->fallback();
+ }
+ template<typename T> T
+ swap (DataKey<T> *key,
+ T data)
+ {
+ NodeBase *nb = get_data (reinterpret_cast<DataKey<void>*> (key));
+ if (nb)
+ {
+ Node<T> *node = reinterpret_cast<Node<T>*> (nb);
+ return node->swap (data);
+ }
+ else
+ {
+ set (key, data);
+ return key->fallback();
+ }
+ }
+ template<typename T> T
+ swap (DataKey<T> *key)
+ {
+ NodeBase *nb = rip_data (reinterpret_cast<DataKey<void>*> (key));
+ if (nb)
+ {
+ Node<T> *node = reinterpret_cast<Node<T>*> (nb);
+ T d = node->get_data();
+ nb->key = NULL; // rip key to prevent data destruction
+ delete nb;
+ return d;
+ }
+ else
+ return key->fallback();
+ }
+ template<typename T> void
+ del (DataKey<T> *key)
+ {
+ NodeBase *nb = rip_data (reinterpret_cast<DataKey<void>*> (key));
+ if (nb)
+ delete nb;
+ }
+ void clear_like_destructor();
+ ~DataList();
+private:
+ void set_data (NodeBase *node);
+ NodeBase* get_data (DataKey<void> *key) const;
+ NodeBase* rip_data (DataKey<void> *key);
+};
+
+/** DataListContainer - typesafe storage and retrieval of arbitrary members.
+ * By using a DataKey, DataListContainer objects allow storage and retrieval of custom data members in a
typesafe fashion.
+ * The custom data members will initially default to DataKey::fallback and are deleted by the
DataListContainer destructor.
+ * Example: @snippet tests/t201/rcore-basics-datalist.cc DataListContainer-EXAMPLE
+ */
+class DataListContainer {
+ DataList data_list;
+public: /// @name Accessing custom data members
+ /// Assign @a data to the custom keyed data member, deletes any previously set data.
+ template<typename Type> inline void set_data (DataKey<Type> *key, Type data) { data_list.set (key,
data); }
+ /// Retrieve contents of the custom keyed data member, returns DataKey::fallback if nothing was set.
+ template<typename Type> inline Type get_data (DataKey<Type> *key) const { return data_list.get
(key); }
+ /// Swap @a data with the current contents of the custom keyed data member, returns the current contents.
+ template<typename Type> inline Type swap_data (DataKey<Type> *key, Type data) { return data_list.swap
(key, data); }
+ /// Removes and returns the current contents of the custom keyed data member without deleting it.
+ template<typename Type> inline Type swap_data (DataKey<Type> *key) { return data_list.swap
(key); }
+ /// Delete the current contents of the custom keyed data member, invokes DataKey::destroy.
+ template<typename Type> inline void delete_data (DataKey<Type> *key) { data_list.del (key); }
+};
+
+} // Bse
+
+#endif // __BSE_DATALIST_HH__
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]