ef557b476ac05451c0d681ed2f808f060ec1dac0
[ardour.git] / libs / glibmm2 / glibmm / containerhandle_shared.h
1 // -*- c++ -*-
2 #ifndef _GLIBMM_CONTAINERHANDLE_SHARED_H
3 #define _GLIBMM_CONTAINERHANDLE_SHARED_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 <cstddef>
25 #include <algorithm>
26 #include <iterator>
27 #include <vector>
28 #include <deque>
29 #include <list>
30
31 #include <glib-object.h>
32 #include <glib/gmem.h>
33 #include <glibmm/refptr.h>
34 #include <glibmm/ustring.h>
35 #include <glibmm/wrap.h>
36 #include <glibmm/debug.h>
37
38 #include <glibmmconfig.h>
39 GLIBMM_USING_STD(forward_iterator_tag)
40 GLIBMM_USING_STD(random_access_iterator_tag)
41 GLIBMM_USING_STD(distance)
42 GLIBMM_USING_STD(copy)
43 GLIBMM_USING_STD(vector)
44 GLIBMM_USING_STD(deque)
45 GLIBMM_USING_STD(list)
46
47
48 namespace Glib
49 {
50
51 /** @defgroup ContHandles Generic container converters
52  */
53
54 /**
55  * @ingroup ContHandles
56  */
57 enum OwnershipType
58 {
59   OWNERSHIP_NONE = 0,
60   OWNERSHIP_SHALLOW, //Release the list, but not its elements, when the container is deleted
61   OWNERSHIP_DEEP //Release the list, and its elements, when the container is deleted.
62 };
63
64
65 /** Utility class holding an iterator sequence.
66  * @ingroup ContHandles
67  * This can be used to initialize a Glib container handle (such as
68  * Glib::ArrayHandle) with an iterator sequence.  Use the helper
69  * function Glib::sequence() to create a Sequence<> object.
70  */
71 template <class Iterator>
72 class Sequence
73 {
74 private:
75   Iterator pbegin_;
76   Iterator pend_;
77
78 public:
79   Sequence(Iterator pbegin, Iterator pend)
80     : pbegin_(pbegin), pend_(pend) {}
81
82   Iterator begin() const { return pbegin_; }
83   Iterator end()   const { return pend_;   }
84   size_t   size()  const { return std::distance(pbegin_, pend_); }
85 };
86
87 /** Helper function to create a Glib::Sequence<> object, which
88  * in turn can be used to initialize a container handle.
89  * @ingroup ContHandles
90  *
91  * @par Usage example:
92  * @code
93  * combo.set_popdown_strings(Glib::sequence(foo_begin, foo_end));
94  * @endcode
95  */
96 template <class Iterator> inline
97 Sequence<Iterator> sequence(Iterator pbegin, Iterator pend)
98 {
99   return Sequence<Iterator>(pbegin, pend);
100 }
101
102
103 namespace Container_Helpers
104 {
105
106 /** @defgroup ContHelpers Helper classes
107  * @ingroup ContHandles
108  */
109
110 /** Generic TypeTraits implementation.
111  * @ingroup ContHelpers
112  * This can be used if the C++ type is the same as the C type, or if implicit
113  * conversions between the types are available.  Also, the types are required
114  * to implement copy-by-value semantics.  (Ownership is just ignored.)
115  */
116 template <class T>
117 struct TypeTraits
118 {
119   typedef T CppType;
120   typedef T CType;
121   typedef T CTypeNonConst;
122
123   static CType   to_c_type      (const CppType& item) { return item; }
124   static CppType to_cpp_type    (const CType&   item) { return item; }
125   static void    release_c_type (const CType&)        {}
126 };
127
128 #ifndef DOXYGEN_SHOULD_SKIP_THIS /* hide the specializations */
129
130 //For some (proably, more spec-compliant) compilers, these specializations must
131 //be next to the objects that they use.
132 #ifdef GLIBMM_CAN_USE_DYNAMIC_CAST_IN_UNUSED_TEMPLATE_WITHOUT_DEFINITION
133
134 /** Partial specialization for pointers to GtkObject instances.
135  * @ingroup ContHelpers
136  */
137 template <class T>
138 struct TypeTraits<T*>
139 {
140   typedef T *                          CppType;
141   typedef typename T::BaseObjectType * CType;
142   typedef typename T::BaseObjectType * CTypeNonConst;
143
144   static CType   to_c_type      (CppType ptr) { return Glib::unwrap(ptr);      }
145   static CType   to_c_type      (CType   ptr) { return ptr;                    }
146   static CppType to_cpp_type    (CType   ptr)
147   {
148     //We copy/paste the widget wrap() implementation here,
149     //because we can not use a specific Glib::wrap(T_Impl) overload here,
150     //because that would be "dependent", and g++ 3.4 does not allow that.
151     //The specific Glib::wrap() overloads don't do anything special anyway.
152     GObject* cobj = (GObject*)ptr;
153     return dynamic_cast<CppType>(Glib::wrap_auto(cobj, false /* take_copy */));
154   }
155   
156   static void    release_c_type (CType   ptr)
157   {
158     GLIBMM_DEBUG_UNREFERENCE(0, ptr);
159     g_object_unref(ptr);
160   }
161 };
162
163 //This confuse the SUN Forte compiler, so we ifdef it out:
164 #ifdef GLIBMM_HAVE_DISAMBIGUOUS_CONST_TEMPLATE_SPECIALIZATIONS 
165
166 /** Partial specialization for pointers to const GtkObject instances.
167  * @ingroup ContHelpers
168  */
169 template <class T>
170 struct TypeTraits<const T*>
171 {
172   typedef const T *                          CppType;
173   typedef const typename T::BaseObjectType * CType;
174   typedef typename T::BaseObjectType *       CTypeNonConst;
175
176   static CType   to_c_type      (CppType ptr) { return Glib::unwrap(ptr);      }
177   static CType   to_c_type      (CType   ptr) { return ptr;                    }
178   static CppType to_cpp_type    (CType   ptr)
179   {
180      //We copy/paste the widget wrap() implementation here,
181      //because we can not use a specific Glib::wrap(T_Impl) overload here,
182      //because that would be "dependent", and g++ 3.4 does not allow that.
183      //The specific Glib::wrap() overloads don't do anything special anyway.
184      GObject* cobj = (GObject*)const_cast<CTypeNonConst>(ptr);
185      return dynamic_cast<CppType>(Glib::wrap_auto(cobj, false /* take_copy */));
186   }
187   
188   static void    release_c_type (CType   ptr)
189   {
190     GLIBMM_DEBUG_UNREFERENCE(0, ptr);
191     g_object_unref(const_cast<CTypeNonConst>(ptr));
192   }
193 };
194 #endif //GLIBMM_HAVE_DISAMBIGUOUS_CONST_TEMPLATE_SPECIALIZATIONS
195
196 /** Partial specialization for pointers to GObject instances.
197  * @ingroup ContHelpers
198  * The C++ type is always a Glib::RefPtr<>.
199  */
200 template <class T>
201 struct TypeTraits< Glib::RefPtr<T> >
202 {
203   typedef Glib::RefPtr<T>              CppType;
204   typedef typename T::BaseObjectType * CType;
205   typedef typename T::BaseObjectType * CTypeNonConst;
206
207   static CType   to_c_type      (const CppType& ptr) { return Glib::unwrap(ptr);     }
208   static CType   to_c_type      (CType          ptr) { return ptr;                   }
209   static CppType to_cpp_type    (CType          ptr)
210   {
211     //return Glib::wrap(ptr, true);
212
213     //We copy/paste the wrap() implementation here,
214     //because we can not use a specific Glib::wrap(CType) overload here,
215     //because that would be "dependent", and g++ 3.4 does not allow that.
216     //The specific Glib::wrap() overloads don't do anything special anyway.
217     GObject* cobj = (GObject*)const_cast<CTypeNonConst>(ptr);
218     return Glib::RefPtr<T>( dynamic_cast<T*>(Glib::wrap_auto(cobj, true /* take_copy */)) );
219     //We use dynamic_cast<> in case of multiple inheritance.
220   }
221   
222   static void    release_c_type (CType          ptr)
223   {
224     GLIBMM_DEBUG_UNREFERENCE(0, ptr);
225     g_object_unref(ptr);
226   }
227 };
228
229 //This confuse the SUN Forte compiler, so we ifdef it out:
230 #ifdef GLIBMM_HAVE_DISAMBIGUOUS_CONST_TEMPLATE_SPECIALIZATIONS
231
232 /** Partial specialization for pointers to const GObject instances.
233  * @ingroup ContHelpers
234  * The C++ type is always a Glib::RefPtr<>.
235  */
236 template <class T>
237 struct TypeTraits< Glib::RefPtr<const T> >
238 {
239   typedef Glib::RefPtr<const T>              CppType;
240   typedef const typename T::BaseObjectType * CType;
241   typedef typename T::BaseObjectType *       CTypeNonConst;
242
243   static CType   to_c_type      (const CppType& ptr) { return Glib::unwrap(ptr);     }
244   static CType   to_c_type      (CType          ptr) { return ptr;                   }
245   static CppType to_cpp_type    (CType          ptr)
246   {
247     //return Glib::wrap(ptr, true);
248
249     //We copy/paste the wrap() implementation here,
250     //because we can not use a specific Glib::wrap(CType) overload here,
251     //because that would be "dependent", and g++ 3.4 does not allow that.
252     //The specific Glib::wrap() overloads don't do anything special anyway.
253     GObject* cobj = (GObject*)(ptr);
254     return Glib::RefPtr<const T>( dynamic_cast<const T*>(Glib::wrap_auto(cobj, true /* take_copy */)) );
255     //We use dynamic_cast<> in case of multiple inheritance.
256   }
257   
258   static void    release_c_type (CType          ptr)
259   {
260     GLIBMM_DEBUG_UNREFERENCE(0, ptr);
261     g_object_unref(const_cast<CTypeNonConst>(ptr));
262   }
263 };
264
265 #endif //GLIBMM_HAVE_DISAMBIGUOUS_CONST_TEMPLATE_SPECIALIZATIONS
266
267 #endif //GLIBMM_CAN_USE_DYNAMIC_CAST_IN_UNUSED_TEMPLATE_WITHOUT_DEFINITION
268
269 /** Specialization for UTF-8 strings.
270  * @ingroup ContHelpers
271  * When converting from C++ to C, Glib::ustring will be accepted as well as
272  * std::string and 'const char*'.  However, when converting to the C++ side,
273  * the output type cannot be 'const char*'.
274  */
275 template <>
276 struct TypeTraits<Glib::ustring>
277 {
278   typedef Glib::ustring CppType;
279   typedef const char *  CType;
280   typedef char *        CTypeNonConst;
281
282   static CType to_c_type (const Glib::ustring& str) { return str.c_str(); }
283   static CType to_c_type (const std::string&   str) { return str.c_str(); }
284   static CType to_c_type (CType                str) { return str;         }
285
286   static CppType to_cpp_type(CType str)
287     { return (str) ? Glib::ustring(str) : Glib::ustring(); }
288
289   static void release_c_type(CType str)
290     { g_free(const_cast<CTypeNonConst>(str)); }
291 };
292
293 /** Specialization for std::string.
294  * @ingroup ContHelpers
295  * When converting from C++ to C, std::string will be accepted as well as
296  * 'const char*'.  However, when converting to the C++ side, the output type
297  * cannot be 'const char*'.
298  */
299 template <>
300 struct TypeTraits<std::string>
301 {
302   typedef std::string   CppType;
303   typedef const char *  CType;
304   typedef char *        CTypeNonConst;
305
306   static CType to_c_type (const std::string&   str) { return str.c_str(); }
307   static CType to_c_type (const Glib::ustring& str) { return str.c_str(); }
308   static CType to_c_type (CType                str) { return str;         }
309
310   static CppType to_cpp_type(CType str)
311     { return (str) ? std::string(str) : std::string(); }
312
313   static void release_c_type(CType str)
314     { g_free(const_cast<CTypeNonConst>(str)); }
315 };
316
317 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
318
319
320 #ifndef DOXYGEN_SHOULD_SKIP_THIS
321 #ifndef GLIBMM_HAVE_TEMPLATE_SEQUENCE_CTORS
322
323 /* The STL containers in Sun's libCstd don't support templated sequence
324  * constructors, for "backward compatibility" reasons.  This helper function
325  * is used in the ContainerHandle -> STL-container conversion workarounds.
326  */
327 template <class Cont, class In>
328 void fill_container(Cont& container, In pbegin, In pend)
329 {
330   for(; pbegin != pend; ++pbegin)
331     container.push_back(*pbegin);
332 }
333
334 #endif /* GLIBMM_HAVE_TEMPLATE_SEQUENCE_CTORS */
335 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
336
337 } // namespace Container_Helpers
338
339 } // namespace Glib
340
341
342 #endif /* _GLIBMM_CONTAINERHANDLE_SHARED_H */
343