pcb 4.1.1
An interactive printed circuit board layout editor.

container.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 "gts.h"
00021 
00022 /* GtsContainee */
00023 
00024 static void containee_class_init (GtsContaineeClass * klass)
00025 {
00026   klass->remove_container = NULL;
00027   klass->add_container = NULL;
00028   klass->foreach = NULL;
00029   klass->is_contained = NULL;
00030   klass->replace = NULL;
00031 }
00032 
00033 GtsContaineeClass * gts_containee_class (void)
00034 {
00035   static GtsContaineeClass * klass = NULL;
00036 
00037   if (klass == NULL) {
00038     GtsObjectClassInfo containee_info = {
00039       "GtsContainee",
00040       sizeof (GtsContainee),
00041       sizeof (GtsContaineeClass),
00042       (GtsObjectClassInitFunc) containee_class_init,
00043       (GtsObjectInitFunc) NULL,
00044       (GtsArgSetFunc) NULL,
00045       (GtsArgGetFunc) NULL
00046     };
00047     klass = gts_object_class_new (gts_object_class (),
00048                                   &containee_info);
00049   }
00050 
00051   return klass;
00052 }
00053 
00054 GtsContainee * gts_containee_new (GtsContaineeClass * klass)
00055 {
00056   GtsContainee * object;
00057 
00058   object = GTS_CONTAINEE (gts_object_new (GTS_OBJECT_CLASS (klass)));
00059 
00060   return object;
00061 }
00062 
00063 gboolean gts_containee_is_contained (GtsContainee * item,
00064                                      GtsContainer * c)
00065 {
00066   g_return_val_if_fail (item != NULL, FALSE);
00067   g_return_val_if_fail (c != NULL, FALSE);
00068 
00069   if (GTS_CONTAINEE_CLASS (GTS_OBJECT (item)->klass)->is_contained)
00070     return
00071       (* GTS_CONTAINEE_CLASS (GTS_OBJECT (item)->klass)->is_contained) 
00072       (item, c);
00073   return FALSE;
00074 }
00075 
00076 void gts_containee_replace (GtsContainee * item,
00077                             GtsContainee * with)
00078 {
00079   if (GTS_CONTAINEE_CLASS (GTS_OBJECT (item)->klass)->replace)
00080     (* GTS_CONTAINEE_CLASS (GTS_OBJECT (item)->klass)->replace) (item, with);
00081   if (GTS_CONTAINEE_CLASS (GTS_OBJECT (item)->klass)->foreach) {
00082     (* GTS_CONTAINEE_CLASS (GTS_OBJECT (item)->klass)->foreach) 
00083       (item, (GtsFunc) gts_container_add, with);
00084     (* GTS_CONTAINEE_CLASS (GTS_OBJECT (item)->klass)->foreach) 
00085       (item, (GtsFunc) gts_container_remove, item);
00086   }
00087 }
00088 
00089 /* GtsSListContainee */
00090 
00091 static void slist_containee_destroy (GtsObject * object)
00092 {
00093   GtsSListContainee * item = GTS_SLIST_CONTAINEE (object);
00094   GSList * i;
00095 
00096   i = item->containers;
00097   while (i) {
00098     GSList * next = i->next;
00099 
00100     gts_container_remove (i->data, GTS_CONTAINEE (item));
00101     i = next;
00102   }
00103   g_assert (item->containers == NULL);
00104 
00105   (* GTS_OBJECT_CLASS (gts_slist_containee_class ())->parent_class->destroy) 
00106     (object);
00107 }
00108 
00109 static void slist_containee_remove_container (GtsContainee * i, 
00110                                               GtsContainer * c)
00111 {
00112   GtsSListContainee * item = GTS_SLIST_CONTAINEE (i);
00113   item->containers = g_slist_remove (item->containers, c);
00114 }
00115 
00116 static void slist_containee_add_container (GtsContainee * i, 
00117                                            GtsContainer * c)
00118 {
00119   GtsSListContainee * item = GTS_SLIST_CONTAINEE (i);
00120   if (!g_slist_find (item->containers, c))
00121     item->containers = g_slist_prepend (item->containers, c);
00122 }
00123 
00124 static void slist_containee_foreach (GtsContainee * c,
00125                                      GtsFunc func, 
00126                                      gpointer data)
00127 {
00128   GSList * i = GTS_SLIST_CONTAINEE (c)->containers;
00129 
00130   while (i) {
00131     GSList * next = i->next;
00132     
00133     (* func) (i->data, data);
00134     i = next;
00135   }
00136 }
00137 
00138 static gboolean slist_containee_is_contained (GtsContainee * i,
00139                                               GtsContainer * c)
00140 {
00141   return g_slist_find (GTS_SLIST_CONTAINEE (i)->containers, c) ? TRUE : FALSE;
00142 }
00143 
00144 static void slist_containee_class_init (GtsSListContaineeClass * klass)
00145 {
00146   GTS_CONTAINEE_CLASS (klass)->remove_container = 
00147     slist_containee_remove_container;
00148   GTS_CONTAINEE_CLASS (klass)->add_container = 
00149     slist_containee_add_container;
00150   GTS_CONTAINEE_CLASS (klass)->foreach = 
00151     slist_containee_foreach;
00152   GTS_CONTAINEE_CLASS (klass)->is_contained = 
00153     slist_containee_is_contained;
00154 
00155   GTS_OBJECT_CLASS (klass)->destroy = slist_containee_destroy;
00156 }
00157 
00158 static void slist_containee_init (GtsSListContainee * object)
00159 {
00160   object->containers = NULL;
00161 }
00162 
00163 GtsSListContaineeClass * gts_slist_containee_class (void)
00164 {
00165   static GtsSListContaineeClass * klass = NULL;
00166 
00167   if (klass == NULL) {
00168     GtsObjectClassInfo slist_containee_info = {
00169       "GtsSListContainee",
00170       sizeof (GtsSListContainee),
00171       sizeof (GtsSListContaineeClass),
00172       (GtsObjectClassInitFunc) slist_containee_class_init,
00173       (GtsObjectInitFunc) slist_containee_init,
00174       (GtsArgSetFunc) NULL,
00175       (GtsArgGetFunc) NULL
00176     };
00177     klass = gts_object_class_new (GTS_OBJECT_CLASS (gts_containee_class ()),
00178                                   &slist_containee_info);
00179   }
00180 
00181   return klass;
00182 }
00183 
00184 /* GtsContainer */
00185 
00186 static void remove_container (GtsContainee * item, GtsContainer * c)
00187 {
00188   if (GTS_CONTAINEE_CLASS (GTS_OBJECT (item)->klass)->remove_container)
00189     (* GTS_CONTAINEE_CLASS (GTS_OBJECT (item)->klass)->remove_container) 
00190       (item, c);
00191 }
00192 
00193 static void container_destroy (GtsObject * object)
00194 {
00195   GtsContainer * c = GTS_CONTAINER (object);
00196 
00197   gts_container_foreach (c, (GtsFunc) remove_container, c);
00198 
00199   (* GTS_OBJECT_CLASS (gts_container_class ())->parent_class->destroy) 
00200     (object);
00201 }
00202 
00203 static void container_add (GtsContainer * c, GtsContainee * item)
00204 {
00205   if (GTS_CONTAINEE_CLASS (GTS_OBJECT (item)->klass)->add_container)
00206     (* GTS_CONTAINEE_CLASS (GTS_OBJECT (item)->klass)->add_container)
00207       (item, c);
00208 }
00209 
00210 static void container_remove (GtsContainer * c, GtsContainee * item)
00211 {
00212   if (GTS_CONTAINEE_CLASS (GTS_OBJECT (item)->klass)->remove_container)
00213     (* GTS_CONTAINEE_CLASS (GTS_OBJECT (item)->klass)->remove_container)
00214       (item, c);
00215 }
00216 
00217 static void container_clone_add (GtsContainee * item, GtsContainer * clone)
00218 {
00219   gts_container_add (clone, item);
00220 }
00221 
00222 static void container_clone (GtsObject * clone, GtsObject * object)
00223 {
00224   gts_object_init (clone, object->klass);
00225   gts_container_foreach (GTS_CONTAINER (object), 
00226                          (GtsFunc) container_clone_add, clone);
00227 }
00228 
00229 static void container_class_init (GtsContainerClass * klass)
00230 {
00231   klass->add = container_add;
00232   klass->remove = container_remove;
00233   klass->foreach = NULL;
00234   klass->size = NULL;
00235 
00236   GTS_OBJECT_CLASS (klass)->destroy = container_destroy;
00237   GTS_OBJECT_CLASS (klass)->clone = container_clone;
00238 }
00239 
00240 GtsContainerClass * gts_container_class (void)
00241 {
00242   static GtsContainerClass * klass = NULL;
00243 
00244   if (klass == NULL) {
00245     GtsObjectClassInfo container_info = {
00246       "GtsContainer",
00247       sizeof (GtsContainer),
00248       sizeof (GtsContainerClass),
00249       (GtsObjectClassInitFunc) container_class_init,
00250       (GtsObjectInitFunc) NULL,
00251       (GtsArgSetFunc) NULL,
00252       (GtsArgGetFunc) NULL
00253     };
00254     klass = 
00255       gts_object_class_new (GTS_OBJECT_CLASS (gts_slist_containee_class ()), 
00256                             &container_info);
00257   }
00258 
00259   return klass;
00260 }
00261 
00262 GtsContainer * gts_container_new (GtsContainerClass * klass)
00263 {
00264   GtsContainer * object;
00265 
00266   object = GTS_CONTAINER (gts_object_new (GTS_OBJECT_CLASS (klass)));
00267 
00268   return object;
00269 }
00270 
00271 void gts_container_add (GtsContainer * c,
00272                         GtsContainee * item)
00273 {
00274   g_return_if_fail (c != NULL);
00275   g_return_if_fail (item != NULL);
00276 
00277   g_assert (GTS_CONTAINER_CLASS (GTS_OBJECT (c)->klass)->add);
00278   (* GTS_CONTAINER_CLASS (GTS_OBJECT (c)->klass)->add) (c, item);
00279 }
00280 
00281 void gts_container_remove (GtsContainer * c,
00282                            GtsContainee * item)
00283 {
00284   g_return_if_fail (c != NULL);
00285   g_return_if_fail (item != NULL);
00286 
00287   g_assert (GTS_CONTAINER_CLASS (GTS_OBJECT (c)->klass)->remove);
00288   (* GTS_CONTAINER_CLASS (GTS_OBJECT (c)->klass)->remove) (c, item);
00289 }
00290 
00291 void gts_container_foreach (GtsContainer * c,
00292                             GtsFunc func,
00293                             gpointer data)
00294 {
00295   g_return_if_fail (c != NULL);
00296   g_return_if_fail (func != NULL);
00297 
00298   if (GTS_CONTAINER_CLASS (GTS_OBJECT (c)->klass)->foreach)
00299     (* GTS_CONTAINER_CLASS (GTS_OBJECT (c)->klass)->foreach) (c, func, data);
00300 }
00301 
00302 guint gts_container_size (GtsContainer * c)
00303 {
00304   g_return_val_if_fail (c != NULL, 0);
00305 
00306   if (GTS_CONTAINER_CLASS (GTS_OBJECT (c)->klass)->size)
00307     return (* GTS_CONTAINER_CLASS (GTS_OBJECT (c)->klass)->size) (c);
00308   return 0;
00309 }
00310 
00311 /* GtsHashContainer */
00312 
00313 static void hash_container_destroy (GtsObject * object)
00314 {
00315   GHashTable * items = GTS_HASH_CONTAINER (object)->items;
00316 
00317   (* GTS_OBJECT_CLASS (gts_hash_container_class ())->parent_class->destroy) 
00318     (object);
00319 
00320   g_hash_table_destroy (items);
00321 }
00322 
00323 static void hash_container_add (GtsContainer * c, GtsContainee * item)
00324 {
00325   g_return_if_fail (GTS_HASH_CONTAINER (c)->frozen == FALSE);
00326 
00327   g_hash_table_insert (GTS_HASH_CONTAINER (c)->items, item, NULL);
00328 
00329   (* GTS_CONTAINER_CLASS (GTS_OBJECT_CLASS (gts_hash_container_class ())->parent_class)->add) (c, item);
00330 }
00331 
00332 static void hash_container_remove (GtsContainer * c, GtsContainee * item)
00333 {
00334   g_return_if_fail (GTS_HASH_CONTAINER (c)->frozen == FALSE);
00335 
00336   g_hash_table_remove (GTS_HASH_CONTAINER (c)->items, item);
00337 
00338   (* GTS_CONTAINER_CLASS (GTS_OBJECT_CLASS (gts_hash_container_class ())->parent_class)->remove) (c, item);
00339 }
00340 
00341 static void hash_foreach (GtsContainee * item, 
00342                           gpointer item_data, 
00343                           gpointer * info)
00344 {
00345   (* ((GtsFunc) info[0])) (item, info[1]);
00346 }
00347 
00348 static void hash_container_foreach (GtsContainer * c, 
00349                                     GtsFunc func, 
00350                                     gpointer data)
00351 {
00352   gpointer info[2];
00353   
00354   info[0] = func;
00355   info[1] = data;
00356   /* prevent removing or adding items */
00357   GTS_HASH_CONTAINER (c)->frozen = TRUE;
00358   g_hash_table_foreach (GTS_HASH_CONTAINER (c)->items, 
00359                         (GHFunc) hash_foreach, info);
00360   GTS_HASH_CONTAINER (c)->frozen = FALSE;
00361 }
00362 
00363 static guint hash_container_size (GtsContainer * c)
00364 {
00365   return g_hash_table_size (GTS_HASH_CONTAINER (c)->items);
00366 }
00367 
00368 static void hash_container_class_init (GtsHashContainerClass * klass)
00369 {
00370   GTS_CONTAINER_CLASS (klass)->add = hash_container_add;
00371   GTS_CONTAINER_CLASS (klass)->remove = hash_container_remove;
00372   GTS_CONTAINER_CLASS (klass)->foreach = hash_container_foreach;
00373   GTS_CONTAINER_CLASS (klass)->size = hash_container_size;
00374 
00375   GTS_OBJECT_CLASS (klass)->destroy = hash_container_destroy;
00376 }
00377 
00378 static void hash_container_init (GtsHashContainer * object)
00379 {
00380   object->items = g_hash_table_new (NULL, NULL);
00381   object->frozen = FALSE;
00382 }
00383 
00384 GtsHashContainerClass * gts_hash_container_class (void)
00385 {
00386   static GtsHashContainerClass * klass = NULL;
00387 
00388   if (klass == NULL) {
00389     GtsObjectClassInfo hash_container_info = {
00390       "GtsHashContainer",
00391       sizeof (GtsHashContainer),
00392       sizeof (GtsHashContainerClass),
00393       (GtsObjectClassInitFunc) hash_container_class_init,
00394       (GtsObjectInitFunc) hash_container_init,
00395       (GtsArgSetFunc) NULL,
00396       (GtsArgGetFunc) NULL
00397     };
00398     klass = gts_object_class_new (GTS_OBJECT_CLASS (gts_container_class ()),
00399                                   &hash_container_info);
00400   }
00401 
00402   return klass;
00403 }
00404 
00405 /* GtsSListContainer */
00406 
00407 static void slist_container_destroy (GtsObject * object)
00408 {
00409   GSList * items = GTS_SLIST_CONTAINER (object)->items;
00410 
00411   (* GTS_OBJECT_CLASS (gts_slist_container_class ())->parent_class->destroy) 
00412     (object);
00413 
00414   g_slist_free (items);
00415 }
00416 
00417 static void slist_container_add (GtsContainer * c, GtsContainee * item)
00418 {
00419   g_return_if_fail (GTS_SLIST_CONTAINER (c)->frozen == FALSE);
00420 
00421   if (!g_slist_find (GTS_SLIST_CONTAINER (c)->items, item))
00422     GTS_SLIST_CONTAINER (c)->items = 
00423       g_slist_prepend (GTS_SLIST_CONTAINER (c)->items, item);
00424 
00425   (* GTS_CONTAINER_CLASS (GTS_OBJECT_CLASS (gts_slist_container_class ())->parent_class)->add) (c, item);
00426 }
00427 
00428 static void slist_container_remove (GtsContainer * c, GtsContainee * item)
00429 {
00430   g_return_if_fail (GTS_SLIST_CONTAINER (c)->frozen == FALSE);
00431 
00432   GTS_SLIST_CONTAINER (c)->items = 
00433       g_slist_remove (GTS_SLIST_CONTAINER (c)->items, item);
00434 
00435   (* GTS_CONTAINER_CLASS (GTS_OBJECT_CLASS (gts_slist_container_class ())->parent_class)->remove) (c, item);
00436 }
00437 
00438 static void slist_container_foreach (GtsContainer * c, 
00439                                      GtsFunc func, 
00440                                      gpointer data)
00441 {
00442   GSList * i;
00443 
00444   i = GTS_SLIST_CONTAINER (c)->items;
00445   while (i) {
00446     GSList * next = i->next;
00447 
00448     (* func) (i->data, data);
00449     i = next;
00450   }
00451 }
00452 
00453 static guint slist_container_size (GtsContainer * c)
00454 {
00455   return g_slist_length (GTS_SLIST_CONTAINER (c)->items);
00456 }
00457 
00458 static void slist_container_class_init (GtsSListContainerClass * klass)
00459 {
00460   GTS_CONTAINER_CLASS (klass)->add = slist_container_add;
00461   GTS_CONTAINER_CLASS (klass)->remove = slist_container_remove;
00462   GTS_CONTAINER_CLASS (klass)->foreach = slist_container_foreach;
00463   GTS_CONTAINER_CLASS (klass)->size = slist_container_size;
00464 
00465   GTS_OBJECT_CLASS (klass)->destroy = slist_container_destroy;
00466 }
00467 
00468 static void slist_container_init (GtsSListContainer * object)
00469 {
00470   object->items = NULL;
00471   object->frozen = FALSE;
00472 }
00473 
00474 GtsSListContainerClass * gts_slist_container_class (void)
00475 {
00476   static GtsSListContainerClass * klass = NULL;
00477 
00478   if (klass == NULL) {
00479     GtsObjectClassInfo slist_container_info = {
00480       "GtsSListContainer",
00481       sizeof (GtsSListContainer),
00482       sizeof (GtsSListContainerClass),
00483       (GtsObjectClassInitFunc) slist_container_class_init,
00484       (GtsObjectInitFunc) slist_container_init,
00485       (GtsArgSetFunc) NULL,
00486       (GtsArgGetFunc) NULL
00487     };
00488     klass = gts_object_class_new (GTS_OBJECT_CLASS (gts_container_class ()),
00489                                   &slist_container_info);
00490   }
00491 
00492   return klass;
00493 }