2 #ifndef _GLIBMM_SLISTHANDLE_H
3 #define _GLIBMM_SLISTHANDLE_H
7 /* Copyright (C) 2002 The gtkmm Development Team
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
19 * You should have received a copy of the GNU Library General Public
20 * License along with this library; if not, write to the Free
21 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include <glib/gslist.h>
25 #include <glibmm/containerhandle_shared.h>
31 namespace Container_Helpers
34 #ifndef DOXYGEN_SHOULD_SKIP_THIS
36 /* Create and fill a GSList as efficient as possible.
37 * This requires bidirectional iterators.
39 template <class Bi, class Tr>
40 GSList* create_slist(Bi pbegin, Bi pend, Tr)
46 // Use & to force a warning if the iterator returns a temporary object.
47 const void *const item = Tr::to_c_type(*&*--pend);
48 head = g_slist_prepend(head, const_cast<void*>(item));
54 /* Create a GSList from a 0-terminated input sequence.
55 * Build it in reverse order and reverse the whole list afterwards,
56 * because appending to the list would be horribly inefficient.
58 template <class For, class Tr>
59 GSList* create_slist(For pbegin, Tr)
65 // Use & to force a warning if the iterator returns a temporary object.
66 const void *const item = Tr::to_c_type(*&*pbegin);
67 head = g_slist_prepend(head, const_cast<void*>(item));
71 return g_slist_reverse(head);
75 /* Convert from any container that supports bidirectional iterators.
77 template <class Tr, class Cont>
78 struct SListSourceTraits
80 static GSList* get_data(const Cont& cont)
81 { return Glib::Container_Helpers::create_slist(cont.begin(), cont.end(), Tr()); }
83 static const Glib::OwnershipType initial_ownership = Glib::OWNERSHIP_SHALLOW;
86 /* Convert from a 0-terminated array. The Cont
87 * argument must be a pointer to the first element.
89 template <class Tr, class Cont>
90 struct SListSourceTraits<Tr,Cont*>
92 static GSList* get_data(const Cont* array)
93 { return (array) ? Glib::Container_Helpers::create_slist(array, Tr()) : 0; }
95 static const Glib::OwnershipType initial_ownership = Glib::OWNERSHIP_SHALLOW;
98 template <class Tr, class Cont>
99 struct SListSourceTraits<Tr,const Cont*> : SListSourceTraits<Tr,Cont*>
102 /* Convert from a 0-terminated array. The Cont argument must be a pointer
103 * to the first element. For consistency, the array must be 0-terminated,
104 * even though the array size is known at compile time.
106 template <class Tr, class Cont, size_t N>
107 struct SListSourceTraits<Tr,Cont[N]>
109 static GSList* get_data(const Cont* array)
110 { return Glib::Container_Helpers::create_slist(array, array + (N - 1), Tr()); }
112 static const Glib::OwnershipType initial_ownership = Glib::OWNERSHIP_SHALLOW;
115 template <class Tr, class Cont, size_t N>
116 struct SListSourceTraits<Tr,const Cont[N]> : SListSourceTraits<Tr,Cont[N]>
119 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
123 * @ingroup ContHelpers
124 * If a method takes this as an argument, or has this as a return type, then you can use a standard
125 * container such as std::list or std::vector.
128 class SListHandleIterator
131 typedef typename Tr::CppType CppType;
132 typedef typename Tr::CType CType;
134 typedef std::forward_iterator_tag iterator_category;
135 typedef CppType value_type;
136 typedef ptrdiff_t difference_type;
137 typedef value_type reference;
138 typedef void pointer;
140 explicit inline SListHandleIterator(const GSList* node);
142 inline value_type operator*() const;
143 inline SListHandleIterator<Tr> & operator++();
144 inline const SListHandleIterator<Tr> operator++(int);
146 inline bool operator==(const SListHandleIterator<Tr>& rhs) const;
147 inline bool operator!=(const SListHandleIterator<Tr>& rhs) const;
153 } // namespace Container_Helpers
157 * @ingroup ContHandles
159 template < class T, class Tr = Glib::Container_Helpers::TypeTraits<T> >
163 typedef typename Tr::CppType CppType;
164 typedef typename Tr::CType CType;
166 typedef CppType value_type;
167 typedef size_t size_type;
168 typedef ptrdiff_t difference_type;
170 typedef Glib::Container_Helpers::SListHandleIterator<Tr> const_iterator;
171 typedef Glib::Container_Helpers::SListHandleIterator<Tr> iterator;
173 template <class Cont> inline
174 SListHandle(const Cont& container);
176 // Take over ownership of a GSList created by GTK+ functions.
177 inline SListHandle(GSList* glist, Glib::OwnershipType ownership);
179 // Copying clears the ownership flag of the source handle.
180 inline SListHandle(const SListHandle<T,Tr>& other);
184 inline const_iterator begin() const;
185 inline const_iterator end() const;
187 template <class U> inline operator std::vector<U>() const;
188 template <class U> inline operator std::deque<U>() const;
189 template <class U> inline operator std::list<U>() const;
191 template <class Cont> inline
192 void assign_to(Cont& container) const;
193 template <class Out> inline
194 void copy(Out pdest) const;
196 inline GSList* data() const;
197 inline size_t size() const;
198 inline bool empty() const;
202 mutable Glib::OwnershipType ownership_;
204 // No copy assignment.
205 SListHandle<T,Tr>& operator=(const SListHandle<T,Tr>&);
209 /***************************************************************************/
210 /* Inline implementation */
211 /***************************************************************************/
213 #ifndef DOXYGEN_SHOULD_SKIP_THIS
215 namespace Container_Helpers
218 /**** Glib::Container_Helpers::SListHandleIterator<> ***********************/
220 template <class Tr> inline
221 SListHandleIterator<Tr>::SListHandleIterator(const GSList* node)
226 template <class Tr> inline
227 typename SListHandleIterator<Tr>::value_type SListHandleIterator<Tr>::operator*() const
229 return Tr::to_cpp_type(static_cast<typename Tr::CTypeNonConst>(node_->data));
232 template <class Tr> inline
233 SListHandleIterator<Tr>& SListHandleIterator<Tr>::operator++()
239 template <class Tr> inline
240 const SListHandleIterator<Tr> SListHandleIterator<Tr>::operator++(int)
242 const SListHandleIterator<Tr> tmp (*this);
247 template <class Tr> inline
248 bool SListHandleIterator<Tr>::operator==(const SListHandleIterator<Tr>& rhs) const
250 return (node_ == rhs.node_);
253 template <class Tr> inline
254 bool SListHandleIterator<Tr>::operator!=(const SListHandleIterator<Tr>& rhs) const
256 return (node_ != rhs.node_);
259 } // namespace Container_Helpers
262 /**** Glib::SListHandle<> **************************************************/
264 template <class T, class Tr>
265 template <class Cont>
267 SListHandle<T,Tr>::SListHandle(const Cont& container)
269 pslist_ (Glib::Container_Helpers::SListSourceTraits<Tr,Cont>::get_data(container)),
270 ownership_ (Glib::Container_Helpers::SListSourceTraits<Tr,Cont>::initial_ownership)
273 template <class T, class Tr> inline
274 SListHandle<T,Tr>::SListHandle(GSList* gslist, Glib::OwnershipType ownership)
277 ownership_ (ownership)
280 template <class T, class Tr> inline
281 SListHandle<T,Tr>::SListHandle(const SListHandle<T,Tr>& other)
283 pslist_ (other.pslist_),
284 ownership_ (other.ownership_)
286 other.ownership_ = Glib::OWNERSHIP_NONE;
289 template <class T, class Tr>
290 SListHandle<T,Tr>::~SListHandle()
292 if(ownership_ != Glib::OWNERSHIP_NONE)
294 if(ownership_ != Glib::OWNERSHIP_SHALLOW)
296 // Deep ownership: release each container element.
297 for(GSList* node = pslist_; node != 0; node = node->next)
298 Tr::release_c_type(static_cast<typename Tr::CTypeNonConst>(node->data));
300 g_slist_free(pslist_);
304 template <class T, class Tr> inline
305 typename SListHandle<T,Tr>::const_iterator SListHandle<T,Tr>::begin() const
307 return Glib::Container_Helpers::SListHandleIterator<Tr>(pslist_);
310 template <class T, class Tr> inline
311 typename SListHandle<T,Tr>::const_iterator SListHandle<T,Tr>::end() const
313 return Glib::Container_Helpers::SListHandleIterator<Tr>(0);
316 template <class T, class Tr>
319 SListHandle<T,Tr>::operator std::vector<U>() const
321 #ifdef GLIBMM_HAVE_TEMPLATE_SEQUENCE_CTORS
322 return std::vector<U>(this->begin(), this->end());
325 temp.reserve(this->size());
326 Glib::Container_Helpers::fill_container(temp, this->begin(), this->end());
331 template <class T, class Tr>
334 SListHandle<T,Tr>::operator std::deque<U>() const
336 #ifdef GLIBMM_HAVE_TEMPLATE_SEQUENCE_CTORS
337 return std::deque<U>(this->begin(), this->end());
340 Glib::Container_Helpers::fill_container(temp, this->begin(), this->end());
345 template <class T, class Tr>
348 SListHandle<T,Tr>::operator std::list<U>() const
350 #ifdef GLIBMM_HAVE_TEMPLATE_SEQUENCE_CTORS
351 return std::list<U>(this->begin(), this->end());
354 Glib::Container_Helpers::fill_container(temp, this->begin(), this->end());
359 template <class T, class Tr>
360 template <class Cont>
362 void SListHandle<T,Tr>::assign_to(Cont& container) const
364 #ifdef GLIBMM_HAVE_TEMPLATE_SEQUENCE_CTORS
365 container.assign(this->begin(), this->end());
368 Glib::Container_Helpers::fill_container(temp, this->begin(), this->end());
369 container.swap(temp);
373 template <class T, class Tr>
376 void SListHandle<T,Tr>::copy(Out pdest) const
378 std::copy(this->begin(), this->end(), pdest);
381 template <class T, class Tr> inline
382 GSList* SListHandle<T,Tr>::data() const
387 template <class T, class Tr> inline
388 size_t SListHandle<T,Tr>::size() const
390 return g_slist_length(pslist_);
393 template <class T, class Tr> inline
394 bool SListHandle<T,Tr>::empty() const
396 return (pslist_ == 0);
399 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
404 #endif /* _GLIBMM_SLISTHANDLE_H */