From: glenlow Date: Fri, 8 Feb 2008 10:50:53 +0000 (+0000) Subject: agraphattr, agnodeattr and agedgeattr now allow resetting attribute default values... X-Git-Tag: LAST_LIBGRAPH~32^2~4748 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=eecea650722677cfe3b868ac6168e5418bf3f549;p=graphviz agraphattr, agnodeattr and agedgeattr now allow resetting attribute default values; Agraph_t, Agnode_t and Agedge_t now have didset flag --- diff --git a/lib/graph/attribs.c b/lib/graph/attribs.c index 52fefe22e..d393ae508 100644 --- a/lib/graph/attribs.c +++ b/lib/graph/attribs.c @@ -14,6 +14,7 @@ * AT&T Research, Florham Park NJ * **********************************************************/ +#include #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; diff --git a/lib/graph/edge.c b/lib/graph/edge.c index b7b9542f2..522e5179b 100644 --- a/lib/graph/edge.c +++ b/lib/graph/edge.c @@ -14,7 +14,7 @@ * AT&T Research, Florham Park NJ * **********************************************************/ - +#include #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); } diff --git a/lib/graph/graph.c b/lib/graph/graph.c index 6b6b99327..507ee6fa2 100644 --- a/lib/graph/graph.c +++ b/lib/graph/graph.c @@ -14,6 +14,7 @@ * AT&T Research, Florham Park NJ * **********************************************************/ +#include #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); diff --git a/lib/graph/graph.h b/lib/graph/graph.h index b81e05741..27e9d7460 100644 --- a/lib/graph/graph.h +++ b/lib/graph/graph.h @@ -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; diff --git a/lib/graph/node.c b/lib/graph/node.c index 7325f4bf1..659600585 100644 --- a/lib/graph/node.c +++ b/lib/graph/node.c @@ -14,6 +14,7 @@ * AT&T Research, Florham Park NJ * **********************************************************/ +#include #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); }