]> granicus.if.org Git - graphviz/commitdiff
agraphattr, agnodeattr and agedgeattr now allow resetting attribute default values...
authorglenlow <devnull@localhost>
Fri, 8 Feb 2008 10:50:53 +0000 (10:50 +0000)
committerglenlow <devnull@localhost>
Fri, 8 Feb 2008 10:50:53 +0000 (10:50 +0000)
lib/graph/attribs.c
lib/graph/edge.c
lib/graph/graph.c
lib/graph/graph.h
lib/graph/node.c

index 52fefe22e4944525f2c0a84ba12b39aedb965cd7..d393ae508625a31eb4f928a350d309e3d7c4a8f0 100644 (file)
@@ -14,6 +14,7 @@
 *              AT&T Research, Florham Park NJ             *
 **********************************************************/
 
+#include <limits.h>
 
 #define EXTERN
 #include "libgraph.h"
@@ -57,47 +58,59 @@ Agsym_t *agNEWsym(Agdict_t * dict, char *name, char *value)
     return a;
 }
 
-static void obj_init_attr(void *obj, Agsym_t * attr)
+static void obj_init_attr(void *obj, Agsym_t * attr, int isnew)
 {
     int i;
     Agraph_t *gobj;            /* generic object */
 
     gobj = (Agraph_t *) obj;
     i = attr->index;
-    gobj->attr = ALLOC(i + 1, gobj->attr, char *);
-    gobj->attr[i] = agstrdup(attr->value);
+       if (isnew) {
+               gobj->attr = ALLOC(i + 1, gobj->attr, char *);
+               gobj->attr[i] = agstrdup(attr->value);
+               if (i % CHAR_BIT == 0) {
+                       /* allocate in chunks of CHAR_BIT bits */
+                       gobj->didset = ALLOC(i / CHAR_BIT + 1, gobj->didset, char);
+                       gobj->didset[i / CHAR_BIT] = 0;
+               }
+       }
+       else if ((gobj->didset[i / CHAR_BIT] & (1 << (i % CHAR_BIT))) == 0) {
+               /* the i-th attr was not set by agxset, so we can replace it */
+               agstrfree(gobj->attr[i]);
+               gobj->attr[i] = agstrdup(attr->value);
+       }
 }
 
-static void add_graph_attr(Agraph_t * g, Agsym_t * attr)
+static void add_graph_attr(Agraph_t * g, Agsym_t * attr, int isnew)
 {
     Agnode_t *n;
 
     if (g->meta_node) {
        for (n = agfstnode(g->meta_node->graph); n;
             n = agnxtnode(g->meta_node->graph, n))
-           obj_init_attr(agusergraph(n), attr);
+           obj_init_attr(agusergraph(n), attr, isnew);
     } else
-       obj_init_attr(g, attr);
+       obj_init_attr(g, attr, isnew);
 }
 
-static void add_node_attr(Agraph_t * g, Agsym_t * attr)
+static void add_node_attr(Agraph_t * g, Agsym_t * attr, int isnew)
 {
     Agnode_t *n;
     Agproto_t *proto;
 
     for (n = agfstnode(g); n; n = agnxtnode(g, n))
-       obj_init_attr(n, attr);
+       obj_init_attr(n, attr, isnew);
     if (g->meta_node) {
        for (n = agfstnode(g->meta_node->graph); n;
             n = agnxtnode(g->meta_node->graph, n))
            for (proto = agusergraph(n)->proto; proto; proto = proto->prev)
-               obj_init_attr(proto->n, attr);
+               obj_init_attr(proto->n, attr, isnew);
     } else
        for (proto = g->proto; proto; proto = proto->prev)
-           obj_init_attr(proto->n, attr);
+           obj_init_attr(proto->n, attr, isnew);
 }
 
-static void add_edge_attr(Agraph_t * g, Agsym_t * attr)
+static void add_edge_attr(Agraph_t * g, Agsym_t * attr, int isnew)
 {
     Agnode_t *n;
     Agedge_t *e;
@@ -105,41 +118,44 @@ static void add_edge_attr(Agraph_t * g, Agsym_t * attr)
 
     for (n = agfstnode(g); n; n = agnxtnode(g, n))
        for (e = agfstout(g, n); e; e = agnxtout(g, e))
-           obj_init_attr(e, attr);
+           obj_init_attr(e, attr, isnew);
     if (g->meta_node) {
        for (n = agfstnode(g->meta_node->graph); n;
             n = agnxtnode(g->meta_node->graph, n))
            for (proto = agusergraph(n)->proto; proto; proto = proto->prev)
-               obj_init_attr(proto->e, attr);
+               obj_init_attr(proto->e, attr, isnew);
     } else
        for (proto = g->proto; proto; proto = proto->prev)
-           obj_init_attr(proto->e, attr);
+           obj_init_attr(proto->e, attr, isnew);
 }
 
 static Agsym_t *dcl_attr(void *obj, char *name, char *value)
 {
     Agsym_t *rv;
+       int isnew = 1;
 
     rv = agfindattr(obj, name);
     if (rv) {
        if (strcmp(rv->value, value)) {
-           agerr(AGWARN,
-                 "Attribute %s=\"%s\" cannot be redeclared as \"%s\"\n",
-                 name, rv->value, value);
+               agstrfree(rv->value);
+               rv->value = agstrdup(value);
+               isnew = 0;
        }
-       return rv;
+       else
+               return rv;
     }
-    rv = agNEWsym(agdictof(obj), name, value);
+       else
+               rv = agNEWsym(agdictof(obj), name, value);
     if (rv) {
        switch (TAG_OF(obj)) {
        case TAG_GRAPH:
-           add_graph_attr((Agraph_t *) obj, rv);
+           add_graph_attr((Agraph_t *) obj, rv, isnew);
            break;
        case TAG_NODE:
-           add_node_attr(((Agnode_t *) obj)->graph, rv);
+           add_node_attr(((Agnode_t *) obj)->graph, rv, isnew);
            break;
        case TAG_EDGE:
-           add_edge_attr(((Agedge_t *) obj)->head->graph, rv);
+           add_edge_attr(((Agedge_t *) obj)->head->graph, rv, isnew);
            break;
        }
     }
@@ -317,11 +333,14 @@ char *agxget(void *obj, int index)
 
 int agxset(void *obj, int index, char *buf)
 {
-    char **p;
+       char **p;
     if (index >= 0) {
-       p = ((Agraph_t *) obj)->attr;
+       Agraph_t *gobj = (Agraph_t *)obj;
+       p = gobj->attr;
        agstrfree(p[index]);
        p[index] = agstrdup(buf);
+       /* the index-th attr was set by agxset */
+       gobj->didset[index / CHAR_BIT] |= 1 << (index % CHAR_BIT);
        return 0;
     } else
        return -1;
index b7b9542f2f57369f6d338af865143931674c2b7d..522e5179bf0c07e7539e0070d741efce09f4a21c 100644 (file)
@@ -14,7 +14,7 @@
 *              AT&T Research, Florham Park NJ             *
 **********************************************************/
 
-
+#include <limits.h>
 
 #include "libgraph.h"
 
@@ -208,14 +208,19 @@ Agedge_t *agNEWedge(Agraph_t * subg, Agnode_t * tail, Agnode_t * head,
     e->id = subg->univ->max_edge_id++;
 
     nobj = dtsize(subg->univ->edgeattr->dict);
-    if (nobj)
-       e->attr = N_NEW(nobj, char *);
-    else
-       e->attr = NULL;
+    if (nobj) {
+               e->attr = N_NEW(nobj, char *);
+               e->didset = N_NEW((nobj + CHAR_BIT - 1) / CHAR_BIT, char);
+               memset(e->didset, 0, (nobj + CHAR_BIT - 1) / CHAR_BIT);
+       }
+    else {
+               e->attr = NULL;
+               e->didset = NULL;
+       }
     for (i = 0; i < nobj; i++)
-       e->attr[i] =
-           agstrdup(proto ? proto->attr[i] : subg->univ->edgeattr->
-                    list[i]->value);
+               e->attr[i] =
+                       agstrdup(proto ? proto->attr[i] : subg->univ->edgeattr->
+                                list[i]->value);
     return e;
 }
 
@@ -270,6 +275,7 @@ void agFREEedge(Agedge_t * e)
     for (i = 0; i < nobj; i++)
        agstrfree(e->attr[i]);
     free(e->attr);
+       free(e->didset);
     free(e);
 }
 
index 6b6b99327043b5d234f135e92faf12b1c2400fc2..507ee6fa23c32f020afb73c0079eb17057cd1247 100644 (file)
@@ -14,6 +14,7 @@
 *              AT&T Research, Florham Park NJ             *
 **********************************************************/
 
+#include <limits.h>
 
 #include "libgraph.h"
 
@@ -214,22 +215,33 @@ static Agraph_t *agNEWgraph(char *name, Agraph_t * parent, int kind)
        g->univ = agnewdata();
        g->root = g;
        nobj = dtsize(g->univ->globattr->dict);
-       if (nobj)
+       if (nobj) {
            g->attr = N_NEW(nobj, char *);
-       else
+               g->didset = N_NEW((nobj + CHAR_BIT - 1) / CHAR_BIT, char);
+               memset(g->didset, 0, (nobj + CHAR_BIT - 1) / CHAR_BIT);
+       }
+       else {
            g->attr = NULL;
+               g->didset = NULL;
+       }
        for (i = 0; i < nobj; i++)
            g->attr[i] = agstrdup(AG.proto_g->attr[i]);
-    } else {
+       } else {
        g->univ = parent->univ;
        g->root = parent->root;
        nobj = dtsize(parent->univ->globattr->dict);
-       if (nobj)
+       if (nobj) {
            g->attr = N_NEW(nobj, char *);
-       else
+               g->didset = N_NEW((nobj + CHAR_BIT - 1) / CHAR_BIT, char);
+               memset(g->didset, 0, (nobj + CHAR_BIT - 1) / CHAR_BIT);
+       }
+       else {
            g->attr = NULL;
+               g->didset = NULL;
+       }
        for (i = 0; i < nobj; i++)
            g->attr[i] = agstrdup(parent->attr[i]);
+
     }
 
     g->meta_node = NULL;
@@ -363,6 +375,8 @@ void agclose(Agraph_t * g)
     }
     if (g->attr)
        free(g->attr);
+       if (g->didset)
+               free(g->didset);
     if (g == g->root) {
        for (n = agfstnode(g); n; n = nn) {
            nn = agnxtnode(g, n);
index b81e057416b9f6d725868cd653749604caeb1d35..27e9d74603e09ec9976c03ea20a910ff48d34397 100644 (file)
@@ -65,6 +65,7 @@ extern "C" {
        int kind:4;
        int handle:24;
        char **attr;
+       char *didset;
        char *name;
        Agdata_t *univ;
        Dict_t *nodes, *inedges, *outedges;
@@ -79,6 +80,7 @@ extern "C" {
        int pad:4;
        int handle:24;
        char **attr;
+       char *didset;
        char *name;
        int id;
        Agraph_t *graph;
@@ -90,6 +92,7 @@ extern "C" {
        int printkey:4;
        int handle:24;
        char **attr;
+       char *didset;
        Agnode_t *head, *tail;
        int id;
        Agedgeinfo_t u;
index 7325f4bf14b0f24e4546c6c7eaa5a292d7e37d88..659600585f86220383d79437a21977b38c642d39 100644 (file)
@@ -14,6 +14,7 @@
 *              AT&T Research, Florham Park NJ             *
 **********************************************************/
 
+#include <limits.h>
 
 #include "libgraph.h"
 
@@ -118,13 +119,18 @@ Agnode_t *agNEWnode(Agraph_t * subg, char *name, Agnode_t * proto)
     n->id = subg->univ->max_node_id++;
     n->graph = subg->root;
     nobj = dtsize(subg->univ->nodeattr->dict);
-    if (nobj)
-       n->attr = N_NEW(nobj, char *);
-    else
-       n->attr = NULL;
+    if (nobj) {
+               n->attr = N_NEW(nobj, char *);
+               n->didset = N_NEW((nobj + CHAR_BIT - 1) / CHAR_BIT, char);
+               memset(n->didset, 0, (nobj + CHAR_BIT - 1) / CHAR_BIT);
+       }
+    else {
+               n->attr = NULL;
+               n->didset = NULL;
+       }
     for (i = 0; i < nobj; i++)
-       n->attr[i] = agstrdup(proto ? proto->attr[i] :
-                             subg->univ->nodeattr->list[i]->value);
+               n->attr[i] = agstrdup(proto ? proto->attr[i] :
+                       subg->univ->nodeattr->list[i]->value);
     return n;
 }
 
@@ -143,5 +149,6 @@ void agFREEnode(Agnode_t * n)
            agstrfree(n->attr[i]);
     }
     free(n->attr);
+       free(n->didset);
     free(n);
 }