Graphviz 2.29.20120208.0545
lib/circogen/nodelist.c
Go to the documentation of this file.
00001 /* $Id$ $Revision$ */
00002 /* vim:set shiftwidth=4 ts=8: */
00003 
00004 /*************************************************************************
00005  * Copyright (c) 2011 AT&T Intellectual Property 
00006  * All rights reserved. This program and the accompanying materials
00007  * are made available under the terms of the Eclipse Public License v1.0
00008  * which accompanies this distribution, and is available at
00009  * http://www.eclipse.org/legal/epl-v10.html
00010  *
00011  * Contributors: See CVS logs. Details at http://www.graphviz.org/
00012  *************************************************************************/
00013 
00014 
00015 #include        "nodelist.h"
00016 #include        "circular.h"
00017 #include        <assert.h>
00018 
00019 static nodelistitem_t *init_nodelistitem(Agnode_t * n)
00020 {
00021     nodelistitem_t *p = NEW(nodelistitem_t);
00022     p->curr = n;
00023     return p;
00024 }
00025 
00026 nodelist_t *mkNodelist()
00027 {
00028     nodelist_t *list = NEW(nodelist_t);
00029     return list;
00030 }
00031 
00032 void freeNodelist(nodelist_t * list)
00033 {
00034     nodelistitem_t *temp;
00035     nodelistitem_t *next;
00036 
00037     if (!list)
00038         return;
00039 
00040     for (temp = list->first; temp; temp = next) {
00041         next = temp->next;
00042         free(temp);
00043     }
00044     free(list);
00045 }
00046 
00047 /* appendNodelist:
00048  * Add node after one.
00049  * If one == NULL, add n to end.
00050  */
00051 void appendNodelist(nodelist_t * list, nodelistitem_t * one, Agnode_t * n)
00052 {
00053     nodelistitem_t *np = init_nodelistitem(n);
00054 
00055     list->sz++;
00056     if (!one)
00057         one = list->last;
00058     if (one == list->last) {
00059         if (one)
00060             one->next = np;
00061         else
00062             list->first = np;
00063         np->prev = one;
00064         np->next = NULL;
00065         list->last = np;
00066     } else {
00067         nodelistitem_t *temp = one->next;
00068         one->next = np;
00069         np->prev = one;
00070         temp->prev = np;
00071         np->next = temp;
00072     }
00073 }
00074 
00075 #ifdef OLD
00076 /* addNodelist:
00077  * Adds node to end of list if not already present.
00078  */
00079 void addNodelist(nodelist_t * list, Agnode_t * n)
00080 {
00081     nodelistitem_t *temp;
00082     nodelistitem_t *item = 0;
00083 
00084     for (temp = list->first; temp; temp = temp->next) {
00085         if (n == temp->curr) {
00086             item = temp;
00087             break;
00088         }
00089     }
00090 
00091     if (item)
00092         return;
00093 
00094     item = init_nodelistitem(n);
00095     if (list->last) {
00096         list->last->next = item;
00097         item->prev = list->last;
00098     } else
00099         list->first = item;
00100     list->last = item;
00101     list->sz++;
00102 }
00103 
00104 void removeNodelist(nodelist_t * list, Agnode_t * n)
00105 {
00106     nodelistitem_t *temp;
00107 
00108     for (temp = list->first; temp; temp = temp->next) {
00109         if (n == temp->curr) {
00110             list->sz--;
00111             if (temp->prev == NULL) {   /* the first node */
00112                 list->first = temp->next;
00113             } else {
00114                 temp->prev->next = temp->next;
00115             }
00116             if (temp == list->last) {   /* the last node */
00117                 list->last = temp->prev;
00118             } else {
00119                 temp->next->prev = temp->prev;
00120             }
00121             free(temp);
00122             return;
00123         }
00124     }
00125 }
00126 #endif
00127 
00128 /* reverseNodelist;
00129  * Destructively reverse a list.
00130  */
00131 nodelist_t *reverseNodelist(nodelist_t * list)
00132 {
00133     nodelistitem_t *temp;
00134     nodelistitem_t *p;
00135 
00136     for (p = list->first; p; p = p->prev) {
00137         temp = p->next;
00138         p->next = p->prev;
00139         p->prev = temp;
00140     }
00141     temp = list->last;
00142     list->last = list->first;
00143     list->first = temp;
00144     return list;
00145 }
00146 
00147 /* realignNodelist:
00148  * Make np new front of list, with current last hooked to
00149  * current first. I.e., make list circular, then cut between
00150  * np and np->prev.
00151  */
00152 void realignNodelist(nodelist_t * list, nodelistitem_t * np)
00153 {
00154     nodelistitem_t *temp;
00155     nodelistitem_t *prev;
00156 
00157     if (np == list->first)
00158         return;
00159 
00160     temp = list->first;
00161     prev = np->prev;
00162 
00163     list->first = np;
00164     np->prev = NULL;
00165     list->last->next = temp;
00166     temp->prev = list->last;
00167     list->last = prev;
00168     prev->next = NULL;
00169 }
00170 
00171 /* cloneNodelist:
00172  * Create a copy of list.
00173  */
00174 nodelist_t *cloneNodelist(nodelist_t * list)
00175 {
00176     nodelist_t *newlist = mkNodelist();
00177     nodelistitem_t *temp;
00178     nodelistitem_t *prev = 0;
00179 
00180     for (temp = list->first; temp; temp = temp->next) {
00181         appendNodelist(newlist, prev, temp->curr);
00182         prev = newlist->last;
00183     }
00184     return newlist;
00185 }
00186 
00187 /* insertNodelist:
00188  * Remove cn. Then, insert cn before neighbor if pos == 0 and 
00189  * after neighbor otherwise.
00190  */
00191 void
00192 insertNodelist(nodelist_t * list, Agnode_t * cn, Agnode_t * neighbor,
00193                int pos)
00194 {
00195     nodelistitem_t *temp;
00196     nodelistitem_t *prev;
00197     nodelistitem_t *next;
00198     nodelistitem_t *actual = 0;
00199 
00200     for (temp = list->first; temp; temp = temp->next) {
00201         if (temp->curr == cn) {
00202             actual = temp;
00203             prev = actual->prev;
00204             next = actual->next;
00205             if (prev)           /* not first */
00206                 prev->next = next;
00207             else
00208                 list->first = next;
00209 
00210             if (next)           /* not last */
00211                 next->prev = prev;
00212             else
00213                 list->last = prev;
00214             break;
00215         }
00216     }
00217     assert(actual);
00218 
00219     prev = NULL;
00220     for (temp = list->first; temp; temp = temp->next) {
00221         if (temp->curr == neighbor) {
00222             if (pos == 0) {
00223                 if (temp == list->first) {
00224                     list->first = actual;
00225                     actual->next = temp;
00226                     actual->prev = NULL;
00227                     temp->prev = actual;
00228                     return;
00229                 }
00230                 prev->next = actual;
00231                 actual->prev = prev;
00232                 actual->next = temp;
00233                 temp->prev = actual;
00234                 return;
00235             } else {
00236                 if (temp == list->last) {
00237                     list->last = actual;
00238                     actual->next = NULL;
00239                     actual->prev = temp;
00240                     temp->next = actual;
00241                     return;
00242                 }
00243                 actual->prev = temp;
00244                 actual->next = temp->next;
00245                 temp->next->prev = actual;
00246                 temp->next = actual;
00247                 return;
00248             }
00249             break;
00250         }
00251         prev = temp;
00252     }
00253 }
00254 
00255 int sizeNodelist(nodelist_t * list)
00256 {
00257     return list->sz;
00258 #ifdef OLD
00259     int i = 0;
00260     nodelistitem_t *temp = NULL;
00261 
00262     temp = list->first;
00263     while (temp) {
00264         i++;
00265         temp = temp->next;
00266     }
00267     return i;
00268 #endif
00269 }
00270 
00271 #ifdef OLD
00272 /* node_exists:
00273  * Return true if node is in list.
00274  */
00275 int node_exists(nodelist_t * list, Agnode_t * n)
00276 {
00277     nodelistitem_t *temp;
00278 
00279     for (temp = list->first; temp; temp = temp->next) {
00280         if (temp->curr == n) {
00281             return 1;
00282         }
00283     }
00284     return 0;
00285 }
00286 
00287 /* nodename_exists:
00288  * Return true if node with given name is in list.
00289  * Assumes n == np->name for some node np;
00290  */
00291 int nodename_exists(nodelist_t * list, char *n)
00292 {
00293     nodelistitem_t *temp;
00294 
00295     temp = list->first;
00296 
00297     for (temp = list->first; temp; temp = temp->next) {
00298         if (temp->curr->name == n) {
00299             return 1;
00300         }
00301     }
00302     return 0;
00303 }
00304 #endif
00305 
00306 /* node_position:
00307  * Returns index of node n in list, starting at 0.
00308  * Returns -1 if not in list.
00309  */
00310 int node_position(nodelist_t * list, Agnode_t * n)
00311 {
00312     return POSITION(n);
00313 #ifdef OLD
00314     nodelistitem_t *temp;
00315     int i = 0;
00316     char *name = n->name;
00317 
00318     for (temp = list->first; temp; temp = temp->next) {
00319         if (temp->curr->name == name) {
00320             return i;
00321         }
00322         i++;
00323     }
00324     return -1;
00325 #endif
00326 }
00327 
00328 /* concatNodelist:
00329  * attach l2 to l1.
00330  */
00331 static void concatNodelist(nodelist_t * l1, nodelist_t * l2)
00332 {
00333     if (l2->first) {
00334         if (l2->first) {
00335             l1->last->next = l2->first;
00336             l2->first->prev = l1->last;
00337             l1->last = l2->last;
00338             l1->sz += l2->sz;
00339         } else {
00340             *l1 = *l2;
00341         }
00342     }
00343 }
00344 
00345 /* reverse_append;
00346  * Create l1 @ (rev l2)
00347  * Destroys and frees l2.
00348  */
00349 void reverseAppend(nodelist_t * l1, nodelist_t * l2)
00350 {
00351     l2 = reverseNodelist(l2);
00352     concatNodelist(l1, l2);
00353     free(l2);
00354 }
00355 
00356 #ifdef DEBUG
00357 void printNodelist(nodelist_t * list)
00358 {
00359     nodelistitem_t *temp = NULL;
00360 
00361     temp = list->first;
00362     while (temp != NULL) {
00363         fprintf(stderr, "%s ", temp->curr->name);
00364         temp = temp->next;
00365     }
00366     fputs("\n", stderr);
00367 }
00368 #endif