1 #ifndef _GLIBMM_UTILITY_H
2 #define _GLIBMM_UTILITY_H
3 
4 /* Copyright 2002 The gtkmm Development Team
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include <glibmmconfig.h>
21 #include <glibmm/ustring.h>
22 #include <glib.h>
23 #include <memory> //For std::unique_ptr.
24 
25 #ifndef DOXYGEN_SHOULD_SKIP_THIS
26 
27 #ifndef GLIBMM_DISABLE_DEPRECATED
28 /* Occasionally, a struct variable has to be initialized after its definition,
29  * i.e. when using structs as class member data.  For convenience, the macro
30  * GLIBMM_INITIALIZE_STRUCT(Var, Type) is provided.  It even avoids creating
31  * a temporary if the compiler is GCC.
32  *
33  * @deprecated Use e.g. std::memset() instead.
34  * It's not used any more in the code generated by _CLASS_BOXEDTYPE_STATIC.
35  * It generates compiler warnings if __STRICT_ANSI__ is defined.
36  */
37 #if ((__GNUC__ >= 3) || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)) && !defined(__STRICT_ANSI__)
38 
39 #define GLIBMM_INITIALIZE_STRUCT(Var, Type) __builtin_memset(&(Var), 0, sizeof(Type))
40 
41 #else
42 
43 // TODO: This causes warnings like this:
44 //"missing initializer for member"
45 #define GLIBMM_INITIALIZE_STRUCT(Var, Type) \
46   G_STMT_START                              \
47   {                                         \
48     Type const temp_initializer__ = {       \
49       0,                                    \
50     };                                      \
51     (Var) = temp_initializer__;             \
52   }                                         \
53   G_STMT_END
54 
55 #endif
56 #endif // GLIBMM_DISABLE_DEPRECATED
57 
58 namespace Glib
59 {
60 
61 // These are used by gmmproc-generated type conversions:
62 
63 #ifndef GLIBMM_DISABLE_DEPRECATED
64 /** Helper to deal with memory allocated
65  * by GLib functions in an exception-safe manner.
66  *
67  * @deprecated Use make_unique_ptr_gfree() instead.
68  */
69 template <typename T>
70 class ScopedPtr
71 {
72 private:
73   T* ptr_;
74   ScopedPtr(const ScopedPtr<T>&);
75   ScopedPtr<T>& operator=(const ScopedPtr<T>&);
76 
77 public:
ScopedPtr()78   ScopedPtr() : ptr_(nullptr) {}
ScopedPtr(T * ptr)79   explicit ScopedPtr(T* ptr) : ptr_(ptr) {}
~ScopedPtr()80   ~ScopedPtr() noexcept { g_free(ptr_); }
get()81   T* get() const { return ptr_; }
addr()82   T** addr() { return &ptr_; }
83 };
84 #endif // GLIBMM_DISABLE_DEPRECATED
85 
86 /** Helper to deal with memory allocated
87  * by GLib functions in an exception-safe manner.
88  *
89  * This just creates a std::unique_ptr that uses g_free() as its deleter.
90  */
91 template <typename T>
92 std::unique_ptr<T[], decltype(&g_free)>
make_unique_ptr_gfree(T * p)93 make_unique_ptr_gfree(T* p)
94 {
95   return std::unique_ptr<T[], decltype(&g_free)>(p, &g_free);
96 }
97 
98 // TODO: Deprecate this? We don't use it ourselves.
99 /** Removes the const nature of a ptr
100  *
101  */
102 template <class T>
103 inline T*
unconst(const T * t)104 unconst(const T* t)
105 {
106   return const_cast<T*>(t);
107 }
108 
109 // Convert const gchar* to ustring, while treating NULL as empty string.
110 inline Glib::ustring
convert_const_gchar_ptr_to_ustring(const char * str)111 convert_const_gchar_ptr_to_ustring(const char* str)
112 {
113   return (str) ? Glib::ustring(str) : Glib::ustring();
114 }
115 
116 // Convert const gchar* to std::string, while treating NULL as empty string.
117 inline std::string
convert_const_gchar_ptr_to_stdstring(const char * str)118 convert_const_gchar_ptr_to_stdstring(const char* str)
119 {
120   return (str) ? std::string(str) : std::string();
121 }
122 
123 // Convert a non-const gchar* return value to ustring, freeing it too.
124 inline Glib::ustring
convert_return_gchar_ptr_to_ustring(char * str)125 convert_return_gchar_ptr_to_ustring(char* str)
126 {
127   return (str) ? Glib::ustring(Glib::make_unique_ptr_gfree(str).get()) : Glib::ustring();
128 }
129 
130 // Convert a non-const gchar* return value to std::string, freeing it too.
131 inline std::string
convert_return_gchar_ptr_to_stdstring(char * str)132 convert_return_gchar_ptr_to_stdstring(char* str)
133 {
134   return (str) ? std::string(Glib::make_unique_ptr_gfree(str).get()) : std::string();
135 }
136 
137 /** Get a pointer to the C style string in a std::string or Glib::ustring.
138  * If the string is empty, a nullptr is returned.
139  */
140 template <typename T>
141 inline const char*
c_str_or_nullptr(const T & str)142 c_str_or_nullptr(const T& str)
143 {
144   return str.empty() ? nullptr : str.c_str();
145 }
146 
147 // Append type_name to dest, while replacing special characters with '+'.
148 GLIBMM_API
149 void append_canonical_typename(std::string& dest, const char* type_name);
150 
151 // Delete data referred to by a void*.
152 // Instantiations can be used as destroy callbacks in glib functions
153 // that take a GDestroyNotify parameter, such as g_object_set_qdata_full()
154 // and g_option_group_set_translate_func().
155 template <typename T>
156 void
destroy_notify_delete(void * data)157 destroy_notify_delete(void* data)
158 {
159   delete static_cast<T*>(data);
160 }
161 
162 // Conversion between different types of function pointers with
163 // reinterpret_cast can make gcc8 print a warning.
164 // https://github.com/libsigcplusplus/libsigcplusplus/issues/1
165 // https://github.com/libsigcplusplus/libsigcplusplus/issues/8
166 /** Returns the supplied function pointer, cast to a pointer to another function type.
167  *
168  * When a single reinterpret_cast between function pointer types causes a
169  * compiler warning or error, this function may work.
170  *
171  * Qualify calls with namespace names: sigc::internal::function_pointer_cast<>().
172  * If you don't, indirect calls from another library that also contains a
173  * function_pointer_cast<>() (perhaps glibmm), can be ambiguous due to ADL
174  * (argument-dependent lookup).
175  */
176 template <typename T_out, typename T_in>
function_pointer_cast(T_in in)177 inline T_out function_pointer_cast(T_in in)
178 {
179   // The double reinterpret_cast suppresses a warning from gcc8 with the
180   // -Wcast-function-type option.
181   return reinterpret_cast<T_out>(reinterpret_cast<void (*)()>(in));
182 }
183 
184 } // namespace Glib
185 
186 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
187 
188 #endif /* _GLIBMM_UTILITY_H */
189