Revert "Remove GTS sources in favour of the libgts package."
[geda-pcb/pcjc2.git] / gts / object.c
blob5970e50c718e898b49306b5f27775abda3a7a816
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.
20 #include <string.h>
21 #include "gts.h"
22 #include "gts-private.h"
24 static GHashTable * class_table = NULL;
26 static void gts_object_class_init (GtsObjectClass * klass,
27 GtsObjectClass * parent_class)
29 if (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);
36 /**
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
42 * @info.
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,
52 NULL);
53 g_return_val_if_fail (parent_class == NULL ||
54 info->class_size >= parent_class->info.class_size,
55 NULL);
57 klass = g_malloc0 (info->class_size);
58 klass->info = *info;
59 klass->parent_class = parent_class;
60 gts_object_class_init (klass, klass);
62 if (!class_table)
63 class_table = g_hash_table_new (g_str_hash, g_str_equal);
64 g_hash_table_insert (class_table, klass->info.name, klass);
66 return klass;
69 /**
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
74 * instantiated yet.
76 GtsObjectClass * gts_object_class_from_name (const gchar * name)
78 g_return_val_if_fail (name != NULL, NULL);
80 if (!class_table)
81 return NULL;
82 return g_hash_table_lookup (class_table, name);
85 static void object_destroy (GtsObject * object)
87 #ifdef DEBUG_IDENTITY
88 #ifdef DEBUG_LEAKS
89 fprintf (stderr, "destroy %s %p->%d\n",
90 object->klass->info.name,
91 object,
92 id (object));
93 #endif
94 id_remove (object);
95 #endif
96 object->klass = NULL;
97 g_free (object);
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;
110 klass->read = NULL;
111 klass->write = NULL;
112 klass->color = NULL;
113 klass->attributes = NULL;
116 static void object_init (GtsObject * object)
118 object->reserved = NULL;
119 object->flags = 0;
123 * gts_object_class:
125 * Returns: the #GtsObjectClass.
127 GtsObjectClass * gts_object_class (void)
129 static GtsObjectClass * klass = NULL;
131 if (klass == NULL) {
132 GtsObjectClassInfo object_info = {
133 "GtsObject",
134 sizeof (GtsObject),
135 sizeof (GtsObjectClass),
136 (GtsObjectClassInitFunc) object_class_init,
137 (GtsObjectInitFunc) object_init,
138 (GtsArgSetFunc) NULL,
139 (GtsArgGetFunc) NULL
141 klass = gts_object_class_new (NULL, &object_info);
144 return klass;
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,
155 gpointer klass)
157 if (!object) {
158 g_warning ("invalid cast from (NULL) pointer to `%s'",
159 GTS_OBJECT_CLASS (klass)->info.name);
160 return object;
162 if (!((GtsObject *) object)->klass) {
163 g_warning ("invalid unclassed pointer in cast to `%s'",
164 GTS_OBJECT_CLASS (klass)->info.name);
165 return object;
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);
171 return object;
173 return object;
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
182 * @from.
184 gpointer gts_object_class_check_cast (gpointer klass,
185 gpointer from)
187 if (!klass) {
188 g_warning ("invalid cast from (NULL) pointer to `%s'",
189 GTS_OBJECT_CLASS (from)->info.name);
190 return klass;
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);
196 return klass;
198 return klass;
202 * gts_object_init:
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;
219 if (parent_class)
220 gts_object_init (object, parent_class);
221 if (klass->info.object_init_func)
222 (*klass->info.object_init_func) (object);
226 * gts_object_new:
227 * @klass: a #GtsObjectClass.
229 * Returns: a new initialized object of class @klass.
231 GtsObject * gts_object_new (GtsObjectClass * klass)
233 GtsObject * object;
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
242 id_insert (object);
243 #ifdef DEBUG_LEAKS
244 fprintf (stderr, "new %s %p->%d\n", klass->info.name,
245 object,
246 id (object));
247 #endif
248 #endif
250 return object;
254 * gts_object_clone:
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)
264 GtsObject * clone;
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;
271 object_init (clone);
272 (* object->klass->clone) (clone, object);
274 #ifdef DEBUG_IDENTITY
275 id_insert (clone);
276 #ifdef DEBUG_LEAKS
277 fprintf (stderr, "clone %s %p->%d\n", clone->klass->info.name,
278 clone,
279 id (clone));
280 #endif
281 #endif
283 return clone;
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)
329 g_free (klass);
333 * gts_finalize:
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)
340 if (class_table) {
341 g_hash_table_foreach (class_table, (GHFunc) free_class, NULL);
342 g_hash_table_destroy (class_table);
343 class_table = NULL;