#ifndef _GLIBMM_CONTAINERS_H #define _GLIBMM_CONTAINERS_H /* 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 Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #include #include /* for backward compatibility */ #include #include #include #include #ifndef DOXYGEN_SHOULD_SKIP_THIS namespace Glib { template class List_Iterator; template class List_ConstIterator; template 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 List_Iterator_Base { public: using value_type = T; using pointer = T*; using reference = T&; }; /// For instance, List_Iterator< Gtk::Widget > template class List_Iterator : public List_Iterator_Base { public: using iterator_category = std::bidirectional_iterator_tag; using size_type = std::size_t; using difference_type = std::ptrdiff_t; using pointer = typename List_Iterator_Base::pointer; using reference = typename List_Iterator_Base::reference; GList* const* head_; GList* node_; using Self = List_Iterator; List_Iterator(GList* const& head, GList* node) : head_(&head), node_(node) {} List_Iterator() : head_(nullptr), node_(nullptr) {} 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 &**this; } }; /// For instance, SList_Iterator< Gtk::Widget > template class SList_Iterator : public List_Iterator_Base { public: using iterator_category = std::forward_iterator_tag; using size_type = std::size_t; using difference_type = std::ptrdiff_t; using pointer = typename List_Iterator_Base::pointer; using reference = typename List_Iterator_Base::reference; GSList* node_; using Self = SList_Iterator; SList_Iterator(GSList* node) : node_(node) {} SList_Iterator() : node_(nullptr) {} 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 { return reinterpret_cast(node_ ? node_->data : glibmm_null_pointer); } pointer operator->() const { return &**this; } }; // This iterator variation returns T_IFace (wrapped from T_Impl) // For instance, List_Cpp_Iterator is // a little like std::list::iterator template class List_Cpp_Iterator : public List_Iterator_Base { public: using iterator_category = std::bidirectional_iterator_tag; using size_type = std::size_t; using difference_type = std::ptrdiff_t; using pointer = typename List_Iterator_Base::pointer; using reference = typename List_Iterator_Base::reference; using Self = List_Cpp_Iterator; 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_(nullptr), node_(nullptr) {} List_Cpp_Iterator(const Self& src) : head_(src.head_), node_(src.node_) {} reference operator*() const { if (node_ && node_->data) { // We copy/paste the widget wrap() implementation here, // because we can not use a specific Glib::wrap(T_Impl) overload here, // because that would be "dependent", and g++ 3.4 does not allow that. // The specific Glib::wrap() overloads don't do anything special anyway. GObject* cobj = static_cast(node_->data); #ifdef GLIBMM_CAN_USE_DYNAMIC_CAST_IN_UNUSED_TEMPLATE_WITHOUT_DEFINITION return *dynamic_cast(Glib::wrap_auto(cobj, false)); #else // We really do need to use dynamic_cast<>, so I expect problems if this code is used. // murrayc. return *static_cast(Glib::wrap_auto(cobj, false)); #endif } return *static_cast(nullptr); // boom! } pointer operator->() const { return &**this; } 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 List_ReverseIterator : private T_Base { public: using iterator_category = typename T_Base::iterator_category; using size_type = typename T_Base::size_type; using difference_type = typename T_Base::difference_type; using value_type = typename T_Base::value_type; using pointer = typename T_Base::pointer; using reference = typename T_Base::reference; using Self = List_ReverseIterator; 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 List_ConstIterator : public T_Base { public: using iterator_category = typename T_Base::iterator_category; using size_type = typename T_Base::size_type; using difference_type = typename T_Base::difference_type; using value_type = const typename T_Base::value_type; using pointer = const typename T_Base::pointer; using reference = const typename T_Base::reference; using Self = List_ConstIterator; 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 */