advance compilation to include plugin_ui.cc
[ardour.git] / libs / glibmm2 / glibmm / listhandle.h
1 // -*- c++ -*-
2 #ifndef _GLIBMM_LISTHANDLE_H
3 #define _GLIBMM_LISTHANDLE_H
4
5 /* $Id$ */
6
7 /* Copyright (C) 2002 The gtkmm Development Team
8  *
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.
13  *
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.
18  *
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.
22  */
23
24 #include <glib/glist.h>
25 #include <glibmm/containerhandle_shared.h>
26
27
28 namespace Glib
29 {
30
31 namespace Container_Helpers
32 {
33
34 #ifndef DOXYGEN_SHOULD_SKIP_THIS
35
36 /* Create and fill a GList as efficient as possible.
37  * This requires bidirectional iterators.
38  */
39 template <class Bi, class Tr>
40 GList* create_list(Bi pbegin, Bi pend, Tr)
41 {
42   GList* head = 0;
43
44   while(pend != pbegin)
45   {
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_list_prepend(head, const_cast<void*>(item));
49   }
50
51   return head;
52 }
53
54 /* Create a GList 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.
57  */
58 template <class For, class Tr>
59 GList* create_list(For pbegin, Tr)
60 {
61   GList* head = 0;
62
63   while(*pbegin)
64   {
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_list_prepend(head, const_cast<void*>(item));
68     ++pbegin;
69   }
70
71   return g_list_reverse(head);
72 }
73
74
75 /* Convert from any container that supports bidirectional iterators.
76  */
77 template <class Tr, class Cont>
78 struct ListSourceTraits
79 {
80   static GList* get_data(const Cont& cont)
81     { return Glib::Container_Helpers::create_list(cont.begin(), cont.end(), Tr()); }
82
83   static const Glib::OwnershipType initial_ownership = Glib::OWNERSHIP_SHALLOW;
84 };
85
86 /* Convert from a 0-terminated array.  The Cont
87  * argument must be a pointer to the first element.
88  */
89 template <class Tr, class Cont>
90 struct ListSourceTraits<Tr,Cont*>
91 {
92   static GList* get_data(const Cont* array)
93     { return (array) ? Glib::Container_Helpers::create_list(array, Tr()) : 0; }
94
95   static const Glib::OwnershipType initial_ownership = Glib::OWNERSHIP_SHALLOW;
96 };
97
98 template <class Tr, class Cont>
99 struct ListSourceTraits<Tr,const Cont*> : ListSourceTraits<Tr,Cont*>
100 {};
101
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.
105  */
106 template <class Tr, class Cont, size_t N>
107 struct ListSourceTraits<Tr,Cont[N]>
108 {
109   static GList* get_data(const Cont* array)
110     { return Glib::Container_Helpers::create_list(array, array + (N - 1), Tr()); }
111
112   static const Glib::OwnershipType initial_ownership = Glib::OWNERSHIP_SHALLOW;
113 };
114
115 template <class Tr, class Cont, size_t N>
116 struct ListSourceTraits<Tr,const Cont[N]> : ListSourceTraits<Tr,Cont[N]>
117 {};
118
119 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
120
121
122 /**
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.
126  */
127 template <class Tr>
128 class ListHandleIterator
129 {
130 public:
131   typedef typename Tr::CppType        CppType;
132   typedef typename Tr::CType          CType;
133
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;
139
140   explicit inline ListHandleIterator(const GList* node);
141
142   inline value_type                   operator*() const;
143   inline ListHandleIterator<Tr> &     operator++();
144   inline const ListHandleIterator<Tr> operator++(int);
145
146   inline bool operator==(const ListHandleIterator<Tr>& rhs) const;
147   inline bool operator!=(const ListHandleIterator<Tr>& rhs) const;
148
149 private:
150   const GList* node_;
151 };
152
153 } // namespace Container_Helpers
154
155
156 /**
157  * @ingroup ContHandles
158  */
159 template < class T, class Tr = Glib::Container_Helpers::TypeTraits<T> >
160 class ListHandle
161 {
162 public:
163   typedef typename Tr::CppType  CppType;
164   typedef typename Tr::CType    CType;
165
166   typedef CppType               value_type;
167   typedef size_t                size_type;
168   typedef ptrdiff_t             difference_type;
169
170   typedef Glib::Container_Helpers::ListHandleIterator<Tr>  const_iterator;
171   typedef Glib::Container_Helpers::ListHandleIterator<Tr>  iterator;
172
173   template <class Cont> inline
174     ListHandle(const Cont& container);
175
176   // Take over ownership of an array created by GTK+ functions.
177   inline ListHandle(GList* glist, Glib::OwnershipType ownership);
178
179   // Copying clears the ownership flag of the source handle.
180   inline ListHandle(const ListHandle<T,Tr>& other);
181
182   ~ListHandle();
183
184   inline const_iterator begin() const;
185   inline const_iterator end()   const;
186
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;
190
191   template <class Cont> inline
192     void assign_to(Cont& container) const;
193
194   template <class Out> inline
195     void copy(Out pdest) const;
196
197   inline GList* data()  const;
198   inline size_t size()  const;
199   inline bool   empty() const;
200
201 private:
202   GList *                     plist_;
203   mutable Glib::OwnershipType ownership_;
204
205   // No copy assignment.
206   ListHandle<T,Tr>& operator=(const ListHandle<T,Tr>&);
207 };
208
209
210 /***************************************************************************/
211 /*  Inline implementation                                                  */
212 /***************************************************************************/
213
214 #ifndef DOXYGEN_SHOULD_SKIP_THIS
215
216 namespace Container_Helpers
217 {
218
219 /**** Glib::Container_Helpers::ListHandleIterator<> ************************/
220
221 template <class Tr> inline
222 ListHandleIterator<Tr>::ListHandleIterator(const GList* node)
223 :
224   node_ (node)
225 {}
226
227 template <class Tr> inline
228 typename ListHandleIterator<Tr>::value_type ListHandleIterator<Tr>::operator*() const
229 {
230   return Tr::to_cpp_type(static_cast<typename Tr::CTypeNonConst>(node_->data));
231 }
232
233 template <class Tr> inline
234 ListHandleIterator<Tr>& ListHandleIterator<Tr>::operator++()
235 {
236   node_ = node_->next;
237   return *this;
238 }
239
240 template <class Tr> inline
241 const ListHandleIterator<Tr> ListHandleIterator<Tr>::operator++(int)
242 {
243   const ListHandleIterator<Tr> tmp (*this);
244   node_ = node_->next;
245   return tmp;
246 }
247
248 template <class Tr> inline
249 bool ListHandleIterator<Tr>::operator==(const ListHandleIterator<Tr>& rhs) const
250 {
251   return (node_ == rhs.node_);
252 }
253
254 template <class Tr> inline
255 bool ListHandleIterator<Tr>::operator!=(const ListHandleIterator<Tr>& rhs) const
256 {
257   return (node_ != rhs.node_);
258 }
259
260 } // namespace Container_Helpers
261
262
263 /**** Glib::ListHandle<> ***************************************************/
264
265 template <class T, class Tr>
266   template <class Cont>
267 inline
268 ListHandle<T,Tr>::ListHandle(const Cont& container)
269 :
270   plist_     (Glib::Container_Helpers::ListSourceTraits<Tr,Cont>::get_data(container)),
271   ownership_ (Glib::Container_Helpers::ListSourceTraits<Tr,Cont>::initial_ownership)
272 {}
273
274 template <class T, class Tr> inline
275 ListHandle<T,Tr>::ListHandle(GList* glist, Glib::OwnershipType ownership)
276 :
277   plist_     (glist),
278   ownership_ (ownership)
279 {}
280
281 template <class T, class Tr> inline
282 ListHandle<T,Tr>::ListHandle(const ListHandle<T,Tr>& other)
283 :
284   plist_     (other.plist_),
285   ownership_ (other.ownership_)
286 {
287   other.ownership_ = Glib::OWNERSHIP_NONE;
288 }
289
290 template <class T, class Tr>
291 ListHandle<T,Tr>::~ListHandle()
292 {
293   if(ownership_ != Glib::OWNERSHIP_NONE)
294   {
295     if(ownership_ != Glib::OWNERSHIP_SHALLOW)
296     {
297       // Deep ownership: release each container element.
298       for(GList* node = plist_; node != 0; node = node->next)
299         Tr::release_c_type(static_cast<typename Tr::CTypeNonConst>(node->data));
300     }
301     g_list_free(plist_);
302   }
303 }
304
305 template <class T, class Tr> inline
306 typename ListHandle<T,Tr>::const_iterator ListHandle<T,Tr>::begin() const
307 {
308   return Glib::Container_Helpers::ListHandleIterator<Tr>(plist_);
309 }
310
311 template <class T, class Tr> inline
312 typename ListHandle<T,Tr>::const_iterator ListHandle<T,Tr>::end() const
313 {
314   return Glib::Container_Helpers::ListHandleIterator<Tr>(0);
315 }
316
317 template <class T, class Tr>
318   template <class U>
319 inline
320 ListHandle<T,Tr>::operator std::vector<U>() const
321 {
322 #ifdef GLIBMM_HAVE_TEMPLATE_SEQUENCE_CTORS
323   return std::vector<U>(this->begin(), this->end());
324 #else
325   std::vector<U> temp;
326   temp.reserve(this->size());
327   Glib::Container_Helpers::fill_container(temp, this->begin(), this->end());
328   return temp;
329 #endif
330 }
331
332 template <class T, class Tr>
333   template <class U>
334 inline
335 ListHandle<T,Tr>::operator std::deque<U>() const
336 {
337 #ifdef GLIBMM_HAVE_TEMPLATE_SEQUENCE_CTORS
338   return std::deque<U>(this->begin(), this->end());
339 #else
340   std::deque<U> temp;
341   Glib::Container_Helpers::fill_container(temp, this->begin(), this->end());
342   return temp;
343 #endif
344 }
345
346 template <class T, class Tr>
347   template <class U>
348 inline
349 ListHandle<T,Tr>::operator std::list<U>() const
350 {
351 #ifdef GLIBMM_HAVE_TEMPLATE_SEQUENCE_CTORS
352   return std::list<U>(this->begin(), this->end());
353 #else
354   std::list<U> temp;
355   Glib::Container_Helpers::fill_container(temp, this->begin(), this->end());
356   return temp;
357 #endif
358 }
359
360 template <class T, class Tr>
361   template <class Cont>
362 inline
363 void ListHandle<T,Tr>::assign_to(Cont& container) const
364 {
365 #ifdef GLIBMM_HAVE_TEMPLATE_SEQUENCE_CTORS
366   container.assign(this->begin(), this->end());
367 #else
368   Cont temp;
369   Glib::Container_Helpers::fill_container(temp, this->begin(), this->end());
370   container.swap(temp);
371 #endif
372 }
373
374 template <class T, class Tr>
375   template <class Out>
376 inline
377 void ListHandle<T,Tr>::copy(Out pdest) const
378 {
379   std::copy(this->begin(), this->end(), pdest);
380 }
381
382 template <class T, class Tr> inline
383 GList* ListHandle<T,Tr>::data() const
384 {
385   return plist_;
386 }
387
388 template <class T, class Tr> inline
389 size_t ListHandle<T,Tr>::size() const
390 {
391   return g_list_length(plist_);
392 }
393
394 template <class T, class Tr> inline
395 bool ListHandle<T,Tr>::empty() const
396 {
397   return (plist_ == 0);
398 }
399
400 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
401
402 } // namespace Glib
403
404
405 #endif /* _GLIBMM_LISTHANDLE_H */
406