2 #ifndef _GLIBMM_CONTAINERHANDLE_SHARED_H
3 #define _GLIBMM_CONTAINERHANDLE_SHARED_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.
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>
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)
51 /** @defgroup ContHandles Generic container converters
55 * @ingroup ContHandles
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.
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.
71 template <class Iterator>
79 Sequence(Iterator pbegin, Iterator pend)
80 : pbegin_(pbegin), pend_(pend) {}
82 Iterator begin() const { return pbegin_; }
83 Iterator end() const { return pend_; }
84 size_t size() const { return std::distance(pbegin_, pend_); }
87 /** Helper function to create a Glib::Sequence<> object, which
88 * in turn can be used to initialize a container handle.
89 * @ingroup ContHandles
93 * combo.set_popdown_strings(Glib::sequence(foo_begin, foo_end));
96 template <class Iterator> inline
97 Sequence<Iterator> sequence(Iterator pbegin, Iterator pend)
99 return Sequence<Iterator>(pbegin, pend);
103 namespace Container_Helpers
106 /** @defgroup ContHelpers Helper classes
107 * @ingroup ContHandles
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.)
121 typedef T CTypeNonConst;
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&) {}
128 #ifndef DOXYGEN_SHOULD_SKIP_THIS /* hide the specializations */
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
134 /** Partial specialization for pointers to GtkObject instances.
135 * @ingroup ContHelpers
138 struct TypeTraits<T*>
141 typedef typename T::BaseObjectType * CType;
142 typedef typename T::BaseObjectType * CTypeNonConst;
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)
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 */));
156 static void release_c_type (CType ptr)
158 GLIBMM_DEBUG_UNREFERENCE(0, ptr);
163 //This confuse the SUN Forte compiler, so we ifdef it out:
164 #ifdef GLIBMM_HAVE_DISAMBIGUOUS_CONST_TEMPLATE_SPECIALIZATIONS
166 /** Partial specialization for pointers to const GtkObject instances.
167 * @ingroup ContHelpers
170 struct TypeTraits<const T*>
172 typedef const T * CppType;
173 typedef const typename T::BaseObjectType * CType;
174 typedef typename T::BaseObjectType * CTypeNonConst;
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)
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 */));
188 static void release_c_type (CType ptr)
190 GLIBMM_DEBUG_UNREFERENCE(0, ptr);
191 g_object_unref(const_cast<CTypeNonConst>(ptr));
194 #endif //GLIBMM_HAVE_DISAMBIGUOUS_CONST_TEMPLATE_SPECIALIZATIONS
196 /** Partial specialization for pointers to GObject instances.
197 * @ingroup ContHelpers
198 * The C++ type is always a Glib::RefPtr<>.
201 struct TypeTraits< Glib::RefPtr<T> >
203 typedef Glib::RefPtr<T> CppType;
204 typedef typename T::BaseObjectType * CType;
205 typedef typename T::BaseObjectType * CTypeNonConst;
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)
211 //return Glib::wrap(ptr, true);
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.
222 static void release_c_type (CType ptr)
224 GLIBMM_DEBUG_UNREFERENCE(0, ptr);
229 //This confuse the SUN Forte compiler, so we ifdef it out:
230 #ifdef GLIBMM_HAVE_DISAMBIGUOUS_CONST_TEMPLATE_SPECIALIZATIONS
232 /** Partial specialization for pointers to const GObject instances.
233 * @ingroup ContHelpers
234 * The C++ type is always a Glib::RefPtr<>.
237 struct TypeTraits< Glib::RefPtr<const T> >
239 typedef Glib::RefPtr<const T> CppType;
240 typedef const typename T::BaseObjectType * CType;
241 typedef typename T::BaseObjectType * CTypeNonConst;
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)
247 //return Glib::wrap(ptr, true);
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.
258 static void release_c_type (CType ptr)
260 GLIBMM_DEBUG_UNREFERENCE(0, ptr);
261 g_object_unref(const_cast<CTypeNonConst>(ptr));
265 #endif //GLIBMM_HAVE_DISAMBIGUOUS_CONST_TEMPLATE_SPECIALIZATIONS
267 #endif //GLIBMM_CAN_USE_DYNAMIC_CAST_IN_UNUSED_TEMPLATE_WITHOUT_DEFINITION
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*'.
276 struct TypeTraits<Glib::ustring>
278 typedef Glib::ustring CppType;
279 typedef const char * CType;
280 typedef char * CTypeNonConst;
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; }
286 static CppType to_cpp_type(CType str)
287 { return (str) ? Glib::ustring(str) : Glib::ustring(); }
289 static void release_c_type(CType str)
290 { g_free(const_cast<CTypeNonConst>(str)); }
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*'.
300 struct TypeTraits<std::string>
302 typedef std::string CppType;
303 typedef const char * CType;
304 typedef char * CTypeNonConst;
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; }
310 static CppType to_cpp_type(CType str)
311 { return (str) ? std::string(str) : std::string(); }
313 static void release_c_type(CType str)
314 { g_free(const_cast<CTypeNonConst>(str)); }
317 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
320 #ifndef DOXYGEN_SHOULD_SKIP_THIS
321 #ifndef GLIBMM_HAVE_TEMPLATE_SEQUENCE_CTORS
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.
327 template <class Cont, class In>
328 void fill_container(Cont& container, In pbegin, In pend)
330 for(; pbegin != pend; ++pbegin)
331 container.push_back(*pbegin);
334 #endif /* GLIBMM_HAVE_TEMPLATE_SEQUENCE_CTORS */
335 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
337 } // namespace Container_Helpers
342 #endif /* _GLIBMM_CONTAINERHANDLE_SHARED_H */