1 /* Copyright 2002 The gtkmm Development Team
2  *
3  * This library is free software; you can redistribute it and/or
4  * modify it under the terms of the GNU Lesser General Public
5  * License as published by the Free Software Foundation; either
6  * version 2.1 of the License, or (at your option) any later version.
7  *
8  * This library is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * Lesser General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public
14  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
15  */
16 
17 #include <glibmm/value.h>
18 #include <glibmm/utility.h>
19 #include <glib.h>
20 
21 namespace
22 {
23 
24 static void
warn_already_registered(const char * location,const std::string & full_name)25 warn_already_registered(const char* location, const std::string& full_name)
26 {
27   g_warning("file %s: (%s): The type name `%s' has been registered already.\n"
28             "This is not supposed to happen -- please send a mail with detailed "
29             "information about your platform to gtkmm-list@gnome.org.  Thanks.\n",
30     __FILE__, location, full_name.c_str());
31 }
32 
33 } // anonymous namespace
34 
35 namespace Glib
36 {
37 
38 GType
custom_boxed_type_register(const char * type_name,ValueInitFunc init_func,ValueFreeFunc free_func,ValueCopyFunc copy_func)39 custom_boxed_type_register(
40   const char* type_name, ValueInitFunc init_func, ValueFreeFunc free_func, ValueCopyFunc copy_func)
41 {
42   std::string full_name("glibmm__CustomBoxed_");
43   Glib::append_canonical_typename(full_name, type_name);
44 
45   // Templates of the same type _might_ be duplicated when instantiated in
46   // multiple translation units -- I'm not sure whether this is true.  If the
47   // static custom_type_ variable in Value<> is duplicated, then the type
48   // would be registered more than once.
49   //
50   // Lookup the type name to see whether this scenario actually happens.
51   // If this turns out to be common behaviour on some platform the warning
52   // should be removed.
53 
54   if (const GType existing_type = g_type_from_name(full_name.c_str()))
55   {
56     warn_already_registered("Glib::custom_boxed_type_register", full_name);
57     return existing_type;
58   }
59 
60   // Via GTypeValueTable, we can teach GValue how to instantiate,
61   // destroy, and copy arbitrary objects of the C++ type.
62 
63   const GTypeValueTable value_table = {
64     init_func, free_func, copy_func,
65     nullptr, // value_peek_pointer
66     nullptr, // collect_format
67     nullptr, // collect_value
68     nullptr, // lcopy_format
69     nullptr, // lcopy_value
70   };
71 
72   const GTypeInfo type_info = {
73     0, // class_size
74     nullptr, // base_init
75     nullptr, // base_finalize
76     nullptr, // class_init_func
77     nullptr, // class_finalize
78     nullptr, // class_data
79     0, // instance_size
80     0, // n_preallocs
81     nullptr, // instance_init
82     &value_table,
83   };
84 
85   // Don't use g_boxed_type_register_static(), because that wouldn't allow
86   // for a non-NULL default value.  The implementation of g_boxed_copy() will
87   // use our custom GTypeValueTable automatically.
88 
89   return g_type_register_static(G_TYPE_BOXED, full_name.c_str(), &type_info, GTypeFlags(0));
90 }
91 
92 GType
custom_pointer_type_register(const char * type_name)93 custom_pointer_type_register(const char* type_name)
94 {
95   std::string full_name("glibmm__CustomPointer_");
96   Glib::append_canonical_typename(full_name, type_name);
97 
98   // Templates of the same type _might_ be duplicated when instantiated in
99   // multiple translation units -- I'm not sure whether this is true.  If the
100   // static custom_type variable in Value<>::value_type_() is duplicated, then
101   // the type would be registered more than once.
102   //
103   // Lookup the type name to see whether this scenario actually happens.
104   // If this turns out to be common behaviour on some platform the warning
105   // should be removed.
106 
107   if (const GType existing_type = g_type_from_name(full_name.c_str()))
108   {
109     warn_already_registered("Glib::custom_pointer_type_register", full_name);
110     return existing_type;
111   }
112 
113   const GTypeInfo type_info = {
114     0, // class_size
115     nullptr, // base_init
116     nullptr, // base_finalize
117     nullptr, // class_init_func
118     nullptr, // class_finalize
119     nullptr, // class_data
120     0, // instance_size
121     0, // n_preallocs
122     nullptr, // instance_init
123     nullptr, // value_table
124   };
125 
126   // We could probably use g_pointer_type_register_static(), but I want
127   // to keep this function symmetric to custom_boxed_type_register().  Also,
128   // g_pointer_type_register_static() would lookup the type name once again.
129 
130   return g_type_register_static(G_TYPE_POINTER, full_name.c_str(), &type_info, GTypeFlags(0));
131 }
132 
133 } // namespace Glib
134