diff options
author | Murray Cumming <murrayc@src.gnome.org> | 2003-01-07 16:59:16 +0000 |
---|---|---|
committer | Murray Cumming <murrayc@src.gnome.org> | 2003-01-07 16:59:16 +0000 |
commit | 78e5bf1313f67e4cbc67fe01a408d27de7383abd (patch) | |
tree | f832445dad23cd0dcc2a116fcc1469d35316d995 /glib/glibmm/containers.h | |
download | glibmm-78e5bf1313f67e4cbc67fe01a408d27de7383abd.tar.gz |
Initial revision
Diffstat (limited to 'glib/glibmm/containers.h')
-rw-r--r-- | glib/glibmm/containers.h | 358 |
1 files changed, 358 insertions, 0 deletions
diff --git a/glib/glibmm/containers.h b/glib/glibmm/containers.h new file mode 100644 index 00000000..068d58fd --- /dev/null +++ b/glib/glibmm/containers.h @@ -0,0 +1,358 @@ +// -*- c++ -*- +#ifndef _GLIBMM_CONTAINERS_H +#define _GLIBMM_CONTAINERS_H + +/* $Id$ */ + +/* containers.h + * + * Copyright (C) 1998-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/glist.h> +#include <glib/gslist.h> +#include <glibmm/sarray.h> /* for backward compatibility */ + +#include <iterator> +#include <glibmmconfig.h> + +GTKMM_USING_STD(bidirectional_iterator_tag) +GTKMM_USING_STD(forward_iterator_tag) + + +#ifndef DOXYGEN_SHOULD_SKIP_THIS + +namespace Glib +{ + +template <class T> class List_Iterator; +template <class T> class List_ConstIterator; +template <class T> class List_ReverseIterator; + +// Most of these methods in the non-template classes needs to be moved +// to implementation. + +//Daniel Elstner has ideas about generating these per-widget with m4. murrayc. + + +extern GLIBMM_API gpointer glibmm_null_pointer; + +template <class T> +class List_Iterator_Base +{ +public: + typedef T value_type; + typedef T* pointer; + typedef T& reference; +} ; + +///For instance, List_Iterator< Gtk::Widget > +template <class T> +class List_Iterator : public List_Iterator_Base<T> +{ +public: + typedef std::bidirectional_iterator_tag iterator_category; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + + typedef typename List_Iterator_Base<T>::pointer pointer; + typedef typename List_Iterator_Base<T>::reference reference; + + GList* const* head_; + GList* node_; + + typedef List_Iterator<T> Self; + + List_Iterator(GList* const& head, GList* node) + : head_(&head), node_(node) + {} + + List_Iterator() + : head_(0), node_(0) + {} + + List_Iterator(const Self& src) + : head_(src.head_), node_(src.node_) + {} + + bool operator==(const Self& src) const { return node_ == src.node_; } + bool operator!=(const Self& src) const { return node_ != src.node_; } + + Self& operator++() + { + if (!node_) + node_ = g_list_first(*head_); + else + node_ = (GList*)g_list_next(node_); + return *this; + } + + Self operator++(int) + { + Self tmp = *this; + ++*this; + return tmp; + } + + Self& operator--() + { + if (!node_) + node_ = g_list_last(*head_); + else + node_ = (GList*)g_list_previous(node_); + + return *this; + } + + Self operator--(int) + { + Self tmp = *this; + --*this; + return tmp; + } + + reference operator*() const + { + return *(pointer)( node_ ? node_->data : glibmm_null_pointer ); + } + + pointer operator -> () const { return &operator*(); } +}; + +///For instance, SList_Iterator< Gtk::Widget > +template <class T> +class SList_Iterator : public List_Iterator_Base<T> +{ +public: + typedef std::forward_iterator_tag iterator_category; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + + typedef typename List_Iterator_Base<T>::pointer pointer; + typedef typename List_Iterator_Base<T>::reference reference; + + GSList* node_; + typedef SList_Iterator<T> Self; + + SList_Iterator(GSList* node) + : node_(node) + {} + + SList_Iterator() + : node_(0) + {} + + SList_Iterator(const Self& src) + : node_(src.node_) + {} + + bool operator==(const Self& src) const { return node_ == src.node_; } + bool operator!=(const Self& src) const { return node_ != src.node_; } + + Self& operator++() + { + node_ = g_slist_next(node_); + return *this; + } + + Self operator++(int) + { + Self tmp = *this; + ++*this; + return tmp; + } + + reference operator*() const + { + g_assert(node_); + return reinterpret_cast<T&>( node_ ? node_->data : glibmm_null_pointer ); + } + + pointer operator -> () const { return &operator*(); } +}; + + +// This iterator variation returns T_IFace (wrapped from T_Impl) +// For instance, List_Cpp_Iterator<GtkWidget, Gtk::Widget> is a little like std::list<Gtk::Widget>::iterator +template<class T_Impl, class T_IFace> +class List_Cpp_Iterator : public List_Iterator_Base<T_IFace> +{ +public: + typedef std::bidirectional_iterator_tag iterator_category; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + + typedef typename List_Iterator_Base<T_IFace>::pointer pointer; + typedef typename List_Iterator_Base<T_IFace>::reference reference; + + typedef List_Cpp_Iterator<T_Impl, T_IFace> Self; + + GList** head_; + GList* node_; + + bool operator==(const Self& src) const { return node_ == src.node_; } + bool operator!=(const Self& src) const { return node_ != src.node_; } + + List_Cpp_Iterator(GList*& head, GList* node ) + : head_(&head), node_(node ) + {} + + List_Cpp_Iterator() + : head_(0), node_(0) + {} + + List_Cpp_Iterator(const Self& src) + : head_(src.head_), node_(src.node_) + {} + + reference operator*() const + { + if (node_ && node_->data) + return *Glib::wrap(static_cast<T_Impl*>((*node_).data)); + + return *(pointer)glibmm_null_pointer; + } + + pointer operator->() const { return &operator*(); } + + Self& operator++() + { + if (!node_) + node_ = g_list_first(*head_); + else + node_ = (GList *)g_list_next(node_); + + return *this; + } + + Self operator++(int) + { + Self tmp = *this; + ++*this; + return tmp; + } + + Self& operator--() + { + if (!node_) + node_ = g_list_last(*head_); + else + node_ = (GList *)g_list_previous(node_); + + return *this; + } + + Self operator--(int) + { + Self tmp = *this; + --*this; + return tmp; + } + +}; + +template <class T_Base> +class List_ReverseIterator: private T_Base +{ +public: + typedef typename T_Base::iterator_category iterator_category; + typedef typename T_Base::size_type size_type; + typedef typename T_Base::difference_type difference_type; + + typedef typename T_Base::value_type value_type; + typedef typename T_Base::pointer pointer; + typedef typename T_Base::reference reference; + + typedef List_ReverseIterator<T_Base> Self; + + bool operator==(const Self& src) const { return T_Base::operator==(src); } + bool operator!=(const Self& src) const { return T_Base::operator!=(src); } + + List_ReverseIterator(GList* const& head, GList* node) + : T_Base(head, node) + {} + + List_ReverseIterator() + : T_Base() + {} + + List_ReverseIterator(const Self& src) + : T_Base(src) + {} + + List_ReverseIterator(const T_Base& src) + : T_Base(src) + { ++(*this); } + + + Self& operator++() {T_Base::operator--(); return *this;} + Self& operator--() {T_Base::operator++(); return *this;} + Self operator++(int) {Self src = *this; T_Base::operator--(); return src;} + Self operator--(int) {Self src = *this; T_Base::operator++(); return src;} + + reference operator*() const { return T_Base::operator*(); } + pointer operator->() const { return T_Base::operator->(); } +}; + +template <class T_Base> +class List_ConstIterator: public T_Base +{ +public: + typedef typename T_Base::iterator_category iterator_category; + typedef typename T_Base::size_type size_type; + typedef typename T_Base::difference_type difference_type; + + typedef const typename T_Base::value_type value_type; + typedef const typename T_Base::pointer pointer; + typedef const typename T_Base::reference reference; + + typedef List_ConstIterator<T_Base> Self; + + bool operator==(const Self& src) const { return T_Base::operator==(src); } + bool operator!=(const Self& src) const { return T_Base::operator!=(src); } + + List_ConstIterator(GList* const& head, GList* node) + : T_Base(head, node) + {} + + List_ConstIterator() + : T_Base() + {} + + List_ConstIterator(const Self& src) + : T_Base(src) + {} + + List_ConstIterator(const T_Base& src) + : T_Base(src) + {} + + Self& operator++() {T_Base::operator++(); return *this;} + Self& operator--() {T_Base::operator--(); return *this;} + Self operator++(int) {Self src = *this; T_Base::operator++(); return src;} + Self operator--(int) {Self src = *this; T_Base::operator--(); return src;} + + reference operator*() const { return T_Base::operator*(); } + pointer operator->() const { return T_Base::operator->(); } +}; + +} // namespace Glib + +#endif /* DOXYGEN_SHOULD_SKIP_THIS */ + +#endif /* _GLIBMM_CONTAINERS_H */ + |