pcb 4.1.1
An interactive printed circuit board layout editor.

object.c

Go to the documentation of this file.
00001 /* GTS - Library for the manipulation of triangulated surfaces
00002  * Copyright (C) 1999 Stéphane Popinet
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Library General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Library General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Library General Public
00015  * License along with this library; if not, write to the
00016  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00017  * Boston, MA 02111-1307, USA.
00018  */
00019 
00020 #include <string.h>
00021 #include "gts.h"
00022 #include "gts-private.h"
00023 
00024 static GHashTable * class_table = NULL;
00025 
00026 static void gts_object_class_init (GtsObjectClass * klass,
00027                                    GtsObjectClass * parent_class)
00028 {
00029   if (parent_class) {
00030     gts_object_class_init (klass, parent_class->parent_class);
00031     if (parent_class->info.class_init_func)
00032       (*parent_class->info.class_init_func) (klass);
00033   }
00034 }
00035 
00044 gpointer gts_object_class_new (GtsObjectClass * parent_class,
00045                                GtsObjectClassInfo * info)
00046 {
00047   GtsObjectClass * klass;
00048 
00049   g_return_val_if_fail (info != NULL, NULL);
00050   g_return_val_if_fail (parent_class == NULL ||
00051                         info->object_size >= parent_class->info.object_size,
00052                         NULL);
00053   g_return_val_if_fail (parent_class == NULL ||
00054                         info->class_size >= parent_class->info.class_size,
00055                         NULL);
00056 
00057   klass = g_malloc0 (info->class_size);
00058   klass->info = *info;
00059   klass->parent_class = parent_class;
00060   gts_object_class_init (klass, klass);
00061 
00062   if (!class_table)
00063     class_table = g_hash_table_new (g_str_hash, g_str_equal);
00064   g_hash_table_insert (class_table, klass->info.name, klass);
00065 
00066   return klass;
00067 }
00068 
00076 GtsObjectClass * gts_object_class_from_name (const gchar * name)
00077 {
00078   g_return_val_if_fail (name != NULL, NULL);
00079 
00080   if (!class_table)
00081     return NULL;
00082   return g_hash_table_lookup (class_table, name);
00083 }
00084 
00085 static void object_destroy (GtsObject * object)
00086 {
00087 #ifdef DEBUG_IDENTITY
00088 #ifdef DEBUG_LEAKS
00089   fprintf (stderr, "destroy %s %p->%d\n", 
00090            object->klass->info.name,
00091            object, 
00092            id (object));
00093 #endif
00094   id_remove (object);
00095 #endif
00096   object->klass = NULL;
00097   g_free (object);
00098 }
00099 
00100 static void object_clone (GtsObject * clone, GtsObject * object)
00101 {
00102   memcpy (clone, object, object->klass->info.object_size);
00103   clone->reserved = NULL;
00104 }
00105 
00106 static void object_class_init (GtsObjectClass * klass)
00107 {
00108   klass->clone = object_clone;
00109   klass->destroy = object_destroy;
00110   klass->read = NULL;
00111   klass->write = NULL;
00112   klass->color = NULL;  
00113   klass->attributes = NULL;
00114 }
00115 
00116 static void object_init (GtsObject * object)
00117 {
00118   object->reserved = NULL;
00119   object->flags = 0;
00120 }
00121 
00127 GtsObjectClass * gts_object_class (void)
00128 {
00129   static GtsObjectClass * klass = NULL;
00130 
00131   if (klass == NULL) {
00132     GtsObjectClassInfo object_info = {
00133       "GtsObject",
00134       sizeof (GtsObject),
00135       sizeof (GtsObjectClass),
00136       (GtsObjectClassInitFunc) object_class_init,
00137       (GtsObjectInitFunc) object_init,
00138       (GtsArgSetFunc) NULL,
00139       (GtsArgGetFunc) NULL
00140     };
00141     klass = gts_object_class_new (NULL, &object_info);
00142   }
00143 
00144   return klass;
00145 }
00146 
00154 gpointer gts_object_check_cast (gpointer object, 
00155                                 gpointer klass)
00156 {
00157   if (!object) {
00158     g_warning ("invalid cast from (NULL) pointer to `%s'",
00159                GTS_OBJECT_CLASS (klass)->info.name);
00160     return object;
00161   }
00162   if (!((GtsObject *) object)->klass) {
00163     g_warning ("invalid unclassed pointer in cast to `%s'",
00164                GTS_OBJECT_CLASS (klass)->info.name);
00165     return object;
00166   }
00167   if (!gts_object_is_from_class (object, klass)) {
00168     g_warning ("invalid cast from `%s' to `%s'",
00169                ((GtsObject *) object)->klass->info.name,
00170                GTS_OBJECT_CLASS (klass)->info.name);
00171     return object;
00172   }
00173   return object;
00174 }
00175 
00184 gpointer gts_object_class_check_cast (gpointer klass, 
00185                                       gpointer from)
00186 {
00187   if (!klass) {
00188     g_warning ("invalid cast from (NULL) pointer to `%s'",
00189                GTS_OBJECT_CLASS (from)->info.name);
00190     return klass;
00191   }
00192   if (!gts_object_class_is_from_class (klass, from)) {
00193     g_warning ("invalid cast from `%s' to `%s'",
00194                GTS_OBJECT_CLASS (klass)->info.name,
00195                GTS_OBJECT_CLASS (from)->info.name);
00196     return klass;
00197   }
00198   return klass;
00199 }
00200 
00211 void gts_object_init (GtsObject * object, GtsObjectClass * klass)
00212 {
00213   GtsObjectClass * parent_class;
00214 
00215   g_return_if_fail (object != NULL);
00216   g_return_if_fail (klass != NULL);
00217 
00218   parent_class = klass->parent_class;
00219   if (parent_class)
00220     gts_object_init (object, parent_class);
00221   if (klass->info.object_init_func)
00222     (*klass->info.object_init_func) (object);
00223 }
00224 
00231 GtsObject * gts_object_new (GtsObjectClass * klass)
00232 {
00233   GtsObject * object;
00234 
00235   g_return_val_if_fail (klass != NULL, NULL);
00236 
00237   object = g_malloc0 (klass->info.object_size);
00238   object->klass = klass;
00239   gts_object_init (object, klass);
00240 
00241 #ifdef DEBUG_IDENTITY
00242   id_insert (object);
00243 #ifdef DEBUG_LEAKS
00244   fprintf (stderr, "new %s %p->%d\n", klass->info.name, 
00245            object, 
00246            id (object));
00247 #endif
00248 #endif
00249 
00250   return object;
00251 }
00252 
00262 GtsObject * gts_object_clone (GtsObject * object)
00263 {
00264   GtsObject * clone;
00265 
00266   g_return_val_if_fail (object != NULL, NULL);
00267   g_return_val_if_fail (object->klass->clone, NULL);
00268 
00269   clone = g_malloc0 (object->klass->info.object_size);
00270   clone->klass = object->klass;
00271   object_init (clone);
00272   (* object->klass->clone) (clone, object);
00273 
00274 #ifdef DEBUG_IDENTITY
00275   id_insert (clone);
00276 #ifdef DEBUG_LEAKS
00277   fprintf (stderr, "clone %s %p->%d\n", clone->klass->info.name, 
00278            clone, 
00279            id (clone));
00280 #endif
00281 #endif
00282 
00283   return clone;
00284 }
00285 
00292 void gts_object_destroy (GtsObject * object)
00293 {
00294   g_assert (object->klass->destroy);
00295   GTS_OBJECT_SET_FLAGS (object, GTS_DESTROYED);
00296   (* object->klass->destroy) (object);
00297 }
00298 
00305 void gts_object_reset_reserved (GtsObject * object)
00306 {
00307   g_return_if_fail (object != NULL);
00308 
00309   object->reserved = NULL;
00310 }
00311 
00319 void gts_object_attributes (GtsObject * object, GtsObject * from)
00320 {
00321   g_return_if_fail (object != NULL);
00322 
00323   if (object->klass->attributes)
00324     (* object->klass->attributes) (object, from);
00325 }
00326 
00327 static void free_class (gchar * name, GtsObjectClass * klass)
00328 {
00329   g_free (klass);
00330 }
00331 
00338 void gts_finalize (void)
00339 {
00340   if (class_table) {
00341     g_hash_table_foreach (class_table, (GHFunc) free_class, NULL);
00342     g_hash_table_destroy (class_table);
00343     class_table = NULL;
00344   }
00345 }