summaryrefslogtreecommitdiff
path: root/libs/glibmm2/glibmm/slisthandle.h
diff options
context:
space:
mode:
Diffstat (limited to 'libs/glibmm2/glibmm/slisthandle.h')
-rw-r--r--libs/glibmm2/glibmm/slisthandle.h405
1 files changed, 405 insertions, 0 deletions
diff --git a/libs/glibmm2/glibmm/slisthandle.h b/libs/glibmm2/glibmm/slisthandle.h
new file mode 100644
index 0000000000..7034914ed3
--- /dev/null
+++ b/libs/glibmm2/glibmm/slisthandle.h
@@ -0,0 +1,405 @@
+// -*- c++ -*-
+#ifndef _GLIBMM_SLISTHANDLE_H
+#define _GLIBMM_SLISTHANDLE_H
+
+/* $Id$ */
+
+/* Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glib/gslist.h>
+#include <glibmm/containerhandle_shared.h>
+
+
+namespace Glib
+{
+
+namespace Container_Helpers
+{
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+/* Create and fill a GSList as efficient as possible.
+ * This requires bidirectional iterators.
+ */
+template <class Bi, class Tr>
+GSList* create_slist(Bi pbegin, Bi pend, Tr)
+{
+ GSList* head = 0;
+
+ while(pend != pbegin)
+ {
+ // Use & to force a warning if the iterator returns a temporary object.
+ const void *const item = Tr::to_c_type(*&*--pend);
+ head = g_slist_prepend(head, const_cast<void*>(item));
+ }
+
+ return head;
+}
+
+/* Create a GSList from a 0-terminated input sequence.
+ * Build it in reverse order and reverse the whole list afterwards,
+ * because appending to the list would be horribly inefficient.
+ */
+template <class For, class Tr>
+GSList* create_slist(For pbegin, Tr)
+{
+ GSList* head = 0;
+
+ while(*pbegin)
+ {
+ // Use & to force a warning if the iterator returns a temporary object.
+ const void *const item = Tr::to_c_type(*&*pbegin);
+ head = g_slist_prepend(head, const_cast<void*>(item));
+ ++pbegin;
+ }
+
+ return g_slist_reverse(head);
+}
+
+
+/* Convert from any container that supports bidirectional iterators.
+ */
+template <class Tr, class Cont>
+struct SListSourceTraits
+{
+ static GSList* get_data(const Cont& cont)
+ { return Glib::Container_Helpers::create_slist(cont.begin(), cont.end(), Tr()); }
+
+ static const Glib::OwnershipType initial_ownership = Glib::OWNERSHIP_SHALLOW;
+};
+
+/* Convert from a 0-terminated array. The Cont
+ * argument must be a pointer to the first element.
+ */
+template <class Tr, class Cont>
+struct SListSourceTraits<Tr,Cont*>
+{
+ static GSList* get_data(const Cont* array)
+ { return (array) ? Glib::Container_Helpers::create_slist(array, Tr()) : 0; }
+
+ static const Glib::OwnershipType initial_ownership = Glib::OWNERSHIP_SHALLOW;
+};
+
+template <class Tr, class Cont>
+struct SListSourceTraits<Tr,const Cont*> : SListSourceTraits<Tr,Cont*>
+{};
+
+/* Convert from a 0-terminated array. The Cont argument must be a pointer
+ * to the first element. For consistency, the array must be 0-terminated,
+ * even though the array size is known at compile time.
+ */
+template <class Tr, class Cont, size_t N>
+struct SListSourceTraits<Tr,Cont[N]>
+{
+ static GSList* get_data(const Cont* array)
+ { return Glib::Container_Helpers::create_slist(array, array + (N - 1), Tr()); }
+
+ static const Glib::OwnershipType initial_ownership = Glib::OWNERSHIP_SHALLOW;
+};
+
+template <class Tr, class Cont, size_t N>
+struct SListSourceTraits<Tr,const Cont[N]> : SListSourceTraits<Tr,Cont[N]>
+{};
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+
+/**
+ * @ingroup ContHelpers
+ * If a method takes this as an argument, or has this as a return type, then you can use a standard
+ * container such as std::list or std::vector.
+ */
+template <class Tr>
+class SListHandleIterator
+{
+public:
+ typedef typename Tr::CppType CppType;
+ typedef typename Tr::CType CType;
+
+ typedef std::forward_iterator_tag iterator_category;
+ typedef CppType value_type;
+ typedef ptrdiff_t difference_type;
+ typedef value_type reference;
+ typedef void pointer;
+
+ explicit inline SListHandleIterator(const GSList* node);
+
+ inline value_type operator*() const;
+ inline SListHandleIterator<Tr> & operator++();
+ inline const SListHandleIterator<Tr> operator++(int);
+
+ inline bool operator==(const SListHandleIterator<Tr>& rhs) const;
+ inline bool operator!=(const SListHandleIterator<Tr>& rhs) const;
+
+private:
+ const GSList* node_;
+};
+
+} // namespace Container_Helpers
+
+
+/**
+ * @ingroup ContHandles
+ */
+template < class T, class Tr = Glib::Container_Helpers::TypeTraits<T> >
+class SListHandle
+{
+public:
+ typedef typename Tr::CppType CppType;
+ typedef typename Tr::CType CType;
+
+ typedef CppType value_type;
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+
+ typedef Glib::Container_Helpers::SListHandleIterator<Tr> const_iterator;
+ typedef Glib::Container_Helpers::SListHandleIterator<Tr> iterator;
+
+ template <class Cont> inline
+ SListHandle(const Cont& container);
+
+ // Take over ownership of a GSList created by GTK+ functions.
+ inline SListHandle(GSList* glist, Glib::OwnershipType ownership);
+
+ // Copying clears the ownership flag of the source handle.
+ inline SListHandle(const SListHandle<T,Tr>& other);
+
+ ~SListHandle();
+
+ inline const_iterator begin() const;
+ inline const_iterator end() const;
+
+ template <class U> inline operator std::vector<U>() const;
+ template <class U> inline operator std::deque<U>() const;
+ template <class U> inline operator std::list<U>() const;
+
+ template <class Cont> inline
+ void assign_to(Cont& container) const;
+ template <class Out> inline
+ void copy(Out pdest) const;
+
+ inline GSList* data() const;
+ inline size_t size() const;
+ inline bool empty() const;
+
+private:
+ GSList * pslist_;
+ mutable Glib::OwnershipType ownership_;
+
+ // No copy assignment.
+ SListHandle<T,Tr>& operator=(const SListHandle<T,Tr>&);
+};
+
+
+/***************************************************************************/
+/* Inline implementation */
+/***************************************************************************/
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+namespace Container_Helpers
+{
+
+/**** Glib::Container_Helpers::SListHandleIterator<> ***********************/
+
+template <class Tr> inline
+SListHandleIterator<Tr>::SListHandleIterator(const GSList* node)
+:
+ node_ (node)
+{}
+
+template <class Tr> inline
+typename SListHandleIterator<Tr>::value_type SListHandleIterator<Tr>::operator*() const
+{
+ return Tr::to_cpp_type(static_cast<typename Tr::CTypeNonConst>(node_->data));
+}
+
+template <class Tr> inline
+SListHandleIterator<Tr>& SListHandleIterator<Tr>::operator++()
+{
+ node_ = node_->next;
+ return *this;
+}
+
+template <class Tr> inline
+const SListHandleIterator<Tr> SListHandleIterator<Tr>::operator++(int)
+{
+ const SListHandleIterator<Tr> tmp (*this);
+ node_ = node_->next;
+ return tmp;
+}
+
+template <class Tr> inline
+bool SListHandleIterator<Tr>::operator==(const SListHandleIterator<Tr>& rhs) const
+{
+ return (node_ == rhs.node_);
+}
+
+template <class Tr> inline
+bool SListHandleIterator<Tr>::operator!=(const SListHandleIterator<Tr>& rhs) const
+{
+ return (node_ != rhs.node_);
+}
+
+} // namespace Container_Helpers
+
+
+/**** Glib::SListHandle<> **************************************************/
+
+template <class T, class Tr>
+ template <class Cont>
+inline
+SListHandle<T,Tr>::SListHandle(const Cont& container)
+:
+ pslist_ (Glib::Container_Helpers::SListSourceTraits<Tr,Cont>::get_data(container)),
+ ownership_ (Glib::Container_Helpers::SListSourceTraits<Tr,Cont>::initial_ownership)
+{}
+
+template <class T, class Tr> inline
+SListHandle<T,Tr>::SListHandle(GSList* gslist, Glib::OwnershipType ownership)
+:
+ pslist_ (gslist),
+ ownership_ (ownership)
+{}
+
+template <class T, class Tr> inline
+SListHandle<T,Tr>::SListHandle(const SListHandle<T,Tr>& other)
+:
+ pslist_ (other.pslist_),
+ ownership_ (other.ownership_)
+{
+ other.ownership_ = Glib::OWNERSHIP_NONE;
+}
+
+template <class T, class Tr>
+SListHandle<T,Tr>::~SListHandle()
+{
+ if(ownership_ != Glib::OWNERSHIP_NONE)
+ {
+ if(ownership_ != Glib::OWNERSHIP_SHALLOW)
+ {
+ // Deep ownership: release each container element.
+ for(GSList* node = pslist_; node != 0; node = node->next)
+ Tr::release_c_type(static_cast<typename Tr::CTypeNonConst>(node->data));
+ }
+ g_slist_free(pslist_);
+ }
+}
+
+template <class T, class Tr> inline
+typename SListHandle<T,Tr>::const_iterator SListHandle<T,Tr>::begin() const
+{
+ return Glib::Container_Helpers::SListHandleIterator<Tr>(pslist_);
+}
+
+template <class T, class Tr> inline
+typename SListHandle<T,Tr>::const_iterator SListHandle<T,Tr>::end() const
+{
+ return Glib::Container_Helpers::SListHandleIterator<Tr>(0);
+}
+
+template <class T, class Tr>
+ template <class U>
+inline
+SListHandle<T,Tr>::operator std::vector<U>() const
+{
+#ifdef GLIBMM_HAVE_TEMPLATE_SEQUENCE_CTORS
+ return std::vector<U>(this->begin(), this->end());
+#else
+ std::vector<U> temp;
+ temp.reserve(this->size());
+ Glib::Container_Helpers::fill_container(temp, this->begin(), this->end());
+ return temp;
+#endif
+}
+
+template <class T, class Tr>
+ template <class U>
+inline
+SListHandle<T,Tr>::operator std::deque<U>() const
+{
+#ifdef GLIBMM_HAVE_TEMPLATE_SEQUENCE_CTORS
+ return std::deque<U>(this->begin(), this->end());
+#else
+ std::deque<U> temp;
+ Glib::Container_Helpers::fill_container(temp, this->begin(), this->end());
+ return temp;
+#endif
+}
+
+template <class T, class Tr>
+ template <class U>
+inline
+SListHandle<T,Tr>::operator std::list<U>() const
+{
+#ifdef GLIBMM_HAVE_TEMPLATE_SEQUENCE_CTORS
+ return std::list<U>(this->begin(), this->end());
+#else
+ std::list<U> temp;
+ Glib::Container_Helpers::fill_container(temp, this->begin(), this->end());
+ return temp;
+#endif
+}
+
+template <class T, class Tr>
+ template <class Cont>
+inline
+void SListHandle<T,Tr>::assign_to(Cont& container) const
+{
+#ifdef GLIBMM_HAVE_TEMPLATE_SEQUENCE_CTORS
+ container.assign(this->begin(), this->end());
+#else
+ Cont temp;
+ Glib::Container_Helpers::fill_container(temp, this->begin(), this->end());
+ container.swap(temp);
+#endif
+}
+
+template <class T, class Tr>
+ template <class Out>
+inline
+void SListHandle<T,Tr>::copy(Out pdest) const
+{
+ std::copy(this->begin(), this->end(), pdest);
+}
+
+template <class T, class Tr> inline
+GSList* SListHandle<T,Tr>::data() const
+{
+ return pslist_;
+}
+
+template <class T, class Tr> inline
+size_t SListHandle<T,Tr>::size() const
+{
+ return g_slist_length(pslist_);
+}
+
+template <class T, class Tr> inline
+bool SListHandle<T,Tr>::empty() const
+{
+ return (pslist_ == 0);
+}
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+} // namespace Glib
+
+
+#endif /* _GLIBMM_SLISTHANDLE_H */
+