1 /* GTS - Library for the manipulation of triangulated surfaces
2 * Copyright (C) 1999 Stéphane Popinet
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
22 #include "gts-private.h"
24 static GHashTable
* class_table
= NULL
;
26 static void gts_object_class_init (GtsObjectClass
* klass
,
27 GtsObjectClass
* parent_class
)
30 gts_object_class_init (klass
, parent_class
->parent_class
);
31 if (parent_class
->info
.class_init_func
)
32 (*parent_class
->info
.class_init_func
) (klass
);
37 * gts_object_class_new:
38 * @parent_class: a #GtsObjectClass.
39 * @info: a #GtsObjectClassInfo, description of the new class to create.
41 * Returns: a new #GtsObjectClass derived from @parent_class and described by
44 gpointer
gts_object_class_new (GtsObjectClass
* parent_class
,
45 GtsObjectClassInfo
* info
)
47 GtsObjectClass
* klass
;
49 g_return_val_if_fail (info
!= NULL
, NULL
);
50 g_return_val_if_fail (parent_class
== NULL
||
51 info
->object_size
>= parent_class
->info
.object_size
,
53 g_return_val_if_fail (parent_class
== NULL
||
54 info
->class_size
>= parent_class
->info
.class_size
,
57 klass
= g_malloc0 (info
->class_size
);
59 klass
->parent_class
= parent_class
;
60 gts_object_class_init (klass
, klass
);
63 class_table
= g_hash_table_new (g_str_hash
, g_str_equal
);
64 g_hash_table_insert (class_table
, klass
->info
.name
, klass
);
70 * gts_object_class_from_name:
71 * @name: the name of a #GtsObjectClass.
73 * Returns: the #GtsObjectClass with name @name or %NULL if it hasn't been
76 GtsObjectClass
* gts_object_class_from_name (const gchar
* name
)
78 g_return_val_if_fail (name
!= NULL
, NULL
);
82 return g_hash_table_lookup (class_table
, name
);
85 static void object_destroy (GtsObject
* object
)
89 fprintf (stderr
, "destroy %s %p->%d\n",
90 object
->klass
->info
.name
,
100 static void object_clone (GtsObject
* clone
, GtsObject
* object
)
102 memcpy (clone
, object
, object
->klass
->info
.object_size
);
103 clone
->reserved
= NULL
;
106 static void object_class_init (GtsObjectClass
* klass
)
108 klass
->clone
= object_clone
;
109 klass
->destroy
= object_destroy
;
113 klass
->attributes
= NULL
;
116 static void object_init (GtsObject
* object
)
118 object
->reserved
= NULL
;
125 * Returns: the #GtsObjectClass.
127 GtsObjectClass
* gts_object_class (void)
129 static GtsObjectClass
* klass
= NULL
;
132 GtsObjectClassInfo object_info
= {
135 sizeof (GtsObjectClass
),
136 (GtsObjectClassInitFunc
) object_class_init
,
137 (GtsObjectInitFunc
) object_init
,
138 (GtsArgSetFunc
) NULL
,
141 klass
= gts_object_class_new (NULL
, &object_info
);
148 * gts_object_check_cast:
149 * @object: a #GtsObject.
150 * @klass: a #GtsObjectClass.
152 * Returns: @object while emitting warnings if @object is not of class @klass.
154 gpointer
gts_object_check_cast (gpointer object
,
158 g_warning ("invalid cast from (NULL) pointer to `%s'",
159 GTS_OBJECT_CLASS (klass
)->info
.name
);
162 if (!((GtsObject
*) object
)->klass
) {
163 g_warning ("invalid unclassed pointer in cast to `%s'",
164 GTS_OBJECT_CLASS (klass
)->info
.name
);
167 if (!gts_object_is_from_class (object
, klass
)) {
168 g_warning ("invalid cast from `%s' to `%s'",
169 ((GtsObject
*) object
)->klass
->info
.name
,
170 GTS_OBJECT_CLASS (klass
)->info
.name
);
177 * gts_object_class_check_cast:
178 * @klass: a #GtsObjectClass.
179 * @from: a #GtsObjectClass.
181 * Returns: @klass while emitting warnings if @klass is not derived from
184 gpointer
gts_object_class_check_cast (gpointer klass
,
188 g_warning ("invalid cast from (NULL) pointer to `%s'",
189 GTS_OBJECT_CLASS (from
)->info
.name
);
192 if (!gts_object_class_is_from_class (klass
, from
)) {
193 g_warning ("invalid cast from `%s' to `%s'",
194 GTS_OBJECT_CLASS (klass
)->info
.name
,
195 GTS_OBJECT_CLASS (from
)->info
.name
);
203 * @object: a #GtsObject.
204 * @klass: a #GtsObjectClass.
206 * Calls the init method of @klass with @object as argument. This is done
207 * recursively in the correct order (from the base class to the top). You
208 * should rarely need this function as it is called automatically by the
209 * constructor for each class.
211 void gts_object_init (GtsObject
* object
, GtsObjectClass
* klass
)
213 GtsObjectClass
* parent_class
;
215 g_return_if_fail (object
!= NULL
);
216 g_return_if_fail (klass
!= NULL
);
218 parent_class
= klass
->parent_class
;
220 gts_object_init (object
, parent_class
);
221 if (klass
->info
.object_init_func
)
222 (*klass
->info
.object_init_func
) (object
);
227 * @klass: a #GtsObjectClass.
229 * Returns: a new initialized object of class @klass.
231 GtsObject
* gts_object_new (GtsObjectClass
* klass
)
235 g_return_val_if_fail (klass
!= NULL
, NULL
);
237 object
= g_malloc0 (klass
->info
.object_size
);
238 object
->klass
= klass
;
239 gts_object_init (object
, klass
);
241 #ifdef DEBUG_IDENTITY
244 fprintf (stderr
, "new %s %p->%d\n", klass
->info
.name
,
255 * @object: a #GtsObject.
257 * Calls the clone method of @object. The call to this function will fail
258 * if no clone method exists for the given object.
260 * Returns: a new object clone of @object.
262 GtsObject
* gts_object_clone (GtsObject
* object
)
266 g_return_val_if_fail (object
!= NULL
, NULL
);
267 g_return_val_if_fail (object
->klass
->clone
, NULL
);
269 clone
= g_malloc0 (object
->klass
->info
.object_size
);
270 clone
->klass
= object
->klass
;
272 (* object
->klass
->clone
) (clone
, object
);
274 #ifdef DEBUG_IDENTITY
277 fprintf (stderr
, "clone %s %p->%d\n", clone
->klass
->info
.name
,
287 * gts_object_destroy:
288 * @object: a #GtsObject.
290 * Calls the destroy method of @object, freeing all memory allocated for it.
292 void gts_object_destroy (GtsObject
* object
)
294 g_assert (object
->klass
->destroy
);
295 GTS_OBJECT_SET_FLAGS (object
, GTS_DESTROYED
);
296 (* object
->klass
->destroy
) (object
);
300 * gts_object_reset_reserved:
301 * @object: a #GtsObject.
303 * Reset the reserved field of @object.
305 void gts_object_reset_reserved (GtsObject
* object
)
307 g_return_if_fail (object
!= NULL
);
309 object
->reserved
= NULL
;
313 * gts_object_attributes:
314 * @object: a #GtsObject.
315 * @from: a #GtsObject.
317 * Calls the attributes() method of @object using @from as source.
319 void gts_object_attributes (GtsObject
* object
, GtsObject
* from
)
321 g_return_if_fail (object
!= NULL
);
323 if (object
->klass
->attributes
)
324 (* object
->klass
->attributes
) (object
, from
);
327 static void free_class (gchar
* name
, GtsObjectClass
* klass
)
335 * Free all the memory allocated by the object system of GTS. No other
336 * GTS function can be called after this function has been called.
338 void gts_finalize (void)
341 g_hash_table_foreach (class_table
, (GHFunc
) free_class
, NULL
);
342 g_hash_table_destroy (class_table
);