1LIBCGRAPH(3) Library Functions Manual LIBCGRAPH(3)
2
3
4
6 libcgraph - abstract graph library
7
9 #include <graphviz/cgraph.h>
10
11 TYPES
12 Agraph_t;
13 Agnode_t;
14 Agedge_t;
15 Agdesc_t;
16 Agdisc_t;
17 Agsym_t;
18 Agrec_t;
19 Agcbdisc_t;
20
21 GLOBALS
22 Agmemdisc_t AgMemDisc;
23 Agiddisc_t AgIdDisc;
24 Agiodisc_t AgIoDisc;
25 Agdisc_t AgDefaultDisc;
26
27 GRAPHS
28 Agraph_t *agopen(char *name, Agdesc_t kind, Agdisc_t *disc);
29 int agclose(Agraph_t *g);
30 Agraph_t *agread(void *channel, Agdisc_t *);
31 Agraph_t *agmemread(char *);
32 void agreadline(int line_no);
33 void agsetfile(char *file_name);
34 Agraph_t *agconcat(Agraph_t *g, void *channel, Agdisc_t *disc)
35 int agwrite(Agraph_t *g, void *channel);
36 int agnnodes(Agraph_t *g),agnedges(Agraph_t *g), agnsubg(Agraph_t * g);
37 int agisdirected(Agraph_t * g),agisundirected(Agraph_t * g),agisstrict(Agraph_t * g), agissimple(Agraph_t * g);
38
39 SUBGRAPHS
40 Agraph_t *agsubg(Agraph_t *g, char *name, int createflag);
41 Agraph_t *agidsubg(Agraph_t * g, unsigned long id, int cflag);
42 Agraph_t *agfstsubg(Agraph_t *g), agnxtsubg(Agraph_t *);
43 Agraph_t *agparent(Agraph_t *g);
44 int agdelsubg(Agraph_t * g, Agraph_t * sub); /* same as agclose() */
45
46 NODES
47 Agnode_t *agnode(Agraph_t *g, char *name, int createflag);
48 Agnode_t *agidnode(Agraph_t *g, ulong id, int createflag);
49 Agnode_t *agsubnode(Agraph_t *g, Agnode_t *n, int createflag);
50 Agnode_t *agfstnode(Agraph_t *g);
51 Agnode_t *agnxtnode(Agraph_t *g, Agnode_t *n);
52 Agnode_t *agprvnode(Agraph_t *g, Agnode_t *n);
53 Agnode_t *aglstnode(Agraph_t *g);
54 int agdelnode(Agraph_t *g, Agnode_t *n);
55 int agdegree(Agraph_t *g, Agnode_t *n, int use_inedges, int use_outedges);
56 int agcountuniqedges(Agraph_t * g, Agnode_t * n, int in, int out);
57
58 EDGES
59 Agedge_t *agedge(Agraph_t* g, Agnode_t *t, Agnode_t *h, char *name, int createflag);
60 Agedge_t *agidedge(Agraph_t * g, Agnode_t * t, Agnode_t * h, unsigned long id, int createflag);
61 Agedge_t *agsubedge(Agraph_t *g, Agedge_t *e, int createflag);
62 Agnode_t *aghead(Agedge_t *e), *agtail(Agedge_t *e);
63 Agedge_t *agfstedge(Agraph_t* g, Agnode_t *n);
64 Agedge_t *agnxtedge(Agraph_t* g, Agedge_t *e, Agnode_t *n);
65 Agedge_t *agfstin(Agraph_t* g, Agnode_t *n);
66 Agedge_t *agnxtin(Agraph_t* g, Agedge_t *e);
67 Agedge_t *agfstout(Agraph_t* g, Agnode_t *n);
68 Agedge_t *agnxtout(Agraph_t* g, Agedge_t *e);
69 int agdeledge(Agraph_t *g, Agedge_t *e);
70 Agedge_t *agopp(Agedge_t *e);
71 int ageqedge(Agedge_t *e0, Agedge_t *e1);
72
73 STRING ATTRIBUTES
74 Agsym_t *agattr(Agraph_t *g, int kind, char *name, const char *value);
75 Agsym_t *agattrsym(void *obj, char *name);
76 Agsym_t *agnxtattr(Agraph_t *g, int kind, Agsym_t *attr);
77 char *agget(void *obj, char *name);
78 char *agxget(void *obj, Agsym_t *sym);
79 int agset(void *obj, char *name, char *value);
80 int agxset(void *obj, Agsym_t *sym, char *value);
81 int agsafeset(void *obj, char *name, char *value, char *def);
82 int agcopyattr(void *, void *);
83
84 RECORDS
85 void *agbindrec(void *obj, char *name, unsigned int size, move_to_front);
86 Agrec_t *aggetrec(void *obj, char *name, int move_to_front);
87 int agdelrec(Agraph_t *g, void *obj, char *name);
88 void aginit(Agraph_t * g, int kind, char *rec_name, int rec_size, int move_to_front);
89 void agclean(Agraph_t * g, int kind, char *rec_name);
90
91 CALLBACKS
92 int *agpopdisc(Agraph_t *g);
93 void agpushdisc(Agraph_t *g, Agcbdisc_t *disc);
94 int agcallbacks(Agraph_t * g, int flag);
95
96 MEMORY
97 void *agalloc(Agraph_t *g, size_t request);
98 void *agrealloc(Agraph_t *g, void *ptr, size_t oldsize, size_t newsize);
99 void agfree(Agraph_t *g, void *ptr);
100
101 STRINGS
102 char *agstrdup(Agraph_t *, char *);
103 char *agstrdup_html(Agraph_t *, char *);
104 int aghtmlstr(char *);
105 char *agstrbind(Agraph_t * g, char *);
106 int strfree(Agraph_t *, char *);
107 char *agcanonStr(char *);
108 char *agstrcanon(char *, char *);
109 char *agcanon(char *, int);
110
111 GENERIC OBJECTS
112 Agraph_t *agraphof(void*);
113 Agraph_t *agroot(void*);
114 int agcontains(Agraph_t*, void*);
115 char *agnameof(void*);
116 void agdelete(Agraph_t *g, void *obj);
117 int agobjkind(void *obj);
118 Agrec_t *AGDATA(void *obj);
119 ulong AGID(void *obj);
120 int AGTYPE(void *obj);
121
122 ERROR REPORTING
123 typedef enum { AGWARN, AGERR, AGMAX, AGPREV } agerrlevel_t;
124 typedef int (*agusererrf) (char*);
125 agerrlevel_t agerrno;
126 agerrlevel_t agseterr(agerrlevel_t);
127 char *aglasterr(void);
128 int agerr(agerrlevel_t level, char *fmt, ...);
129 void agerrorf(char *fmt, ...);
130 void agwarningf(char *fmt, ...);
131 int agerrors(void);
132 agusererrf agseterrf(agusererrf);
133
135 Libcgraph supports graph programming by maintaining graphs in memory
136 and reading and writing graph files. Graphs are composed of nodes,
137 edges, and nested subgraphs. These graph objects may be attributed
138 with string name-value pairs and programmer-defined records (see At‐
139 tributes).
140
141 All of Libcgraph's global symbols have the prefix ag (case varying).
142 In the following, if a function has a parameter int createflag and the
143 object does not exist, the function will create the specified object if
144 createflag is non-zero; otherwise, it will return NULL.
145
147 A ``main'' or ``root'' graph defines a namespace for a collection of
148 graph objects (subgraphs, nodes, edges) and their attributes. Objects
149 may be named by unique strings or by integer IDs.
150
151 agopen creates a new graph with the given name and kind. (Graph kinds
152 are Agdirected, Agundirected, Agstrictdirected, and Agstrictundirected.
153 A strict graph cannot have multi-edges or self-arcs.) The final argu‐
154 ment points to a discpline structure which can be used to tailor I/O,
155 memory allocation, and ID allocation. Typically, a NULL value will be
156 used to indicate the default discipline AgDefaultDisc. agclose deletes
157 a graph, freeing its associated storage. agread, agwrite, and agconcat
158 perform file I/O using the graph file language described below. agread
159 constructs a new graph while agconcat merges the file contents with a
160 pre-existing graph. Though I/O methods may be overridden, the default
161 is that the channel argument is a stdio FILE pointer. agmemread at‐
162 tempts to read a graph from the input string. agsetfile and agreadline
163 are helper functions that simply set the current file name and input
164 line number for subsequent error reporting.
165
166 The functions agisdirected, agisundirected, agisstrict, and agissimple
167 can be used to query if a graph is directed, undirected, strict (at
168 most one edge with a given tail and head), or simple (strict with no
169 loops), respectively,
170
171 agsubg finds or creates a subgraph by name. agidsubg allows a program‐
172 mer to specify the subgraph by a unique integer ID. A new subgraph is
173 initially empty and is of the same kind as its parent. Nested subgraph
174 trees may be created. A subgraph's name is only interpreted relative
175 to its parent. A program can scan subgraphs under a given graph using
176 agfstsubg and agnxtsubg. A subgraph is deleted with agdelsubg (or ag‐
177 close). The agparent function returns the immediate parent graph of a
178 subgraph, or itself if the graph is already a root graph.
179
180 By default, nodes are stored in ordered sets for efficient random ac‐
181 cess to insert, find, and delete nodes. The edges of a node are also
182 stored in ordered sets. The sets are maintained internally as splay
183 tree dictionaries using Phong Vo's cdt library.
184
185 agnnodes, agnedges, and agnsubg return the sizes of node, edge and sub‐
186 graph sets of a graph. The function agdegree returns the size of the
187 edge set of a nodes, and takes flags to select in-edges, out-edges, or
188 both. The function agcountuniqedges returns the size of the edge set
189 of a nodes, and takes flags to select in-edges, out-edges, or both. Un‐
190 like agdegree, each loop is only counted once.
191
193 A node is created by giving a unique string name or programmer defined
194 integer ID, and is represented by a unique internal object. (Node
195 equality can checked by pointer comparison.)
196
197 agnode searches in a graph or subgraph for a node with the given name,
198 and returns it if found. agidnode allows a programmer to specify the
199 node by a unique integer ID. agsubnode performs a similar operation on
200 an existing node and a subgraph.
201
202 agfstnode and agnxtnode scan node lists. agprvnode and aglstnode are
203 symmetric but scan backward. The default sequence is order of creation
204 (object timestamp.) agdelnode removes a node from a graph or subgraph.
205
207 An abstract edge has two endpoint nodes called tail and head where all
208 outedges of the same node have it as the tail value and similarly all
209 inedges have it as the head. In an undirected graph, head and tail are
210 interchangeable. If a graph has multi-edges between the same pair of
211 nodes, the edge's string name behaves as a secondary key.
212
213 agedge searches in a graph or subgraph for an edge between the given
214 endpoints (with an optional multi-edge selector name) and returns it if
215 found or created. Note that, in undirected graphs, a search tries both
216 orderings of the tail and head nodes. If the name is NULL, then an
217 anonymous internal value is generated. agidedge allows a programmer to
218 create an edge by giving its unique integer ID. agsubedge performs a
219 similar operation on an existing edge and a subgraph. agfstin, agnx‐
220 tin, agfstout, and agnxtout visit directed in- and out- edge lists, and
221 ordinarily apply only in directed graphs. agfstedge and agnxtedge
222 visit all edges incident to a node. agtail and aghead get the endpoint
223 of an edge. agdeledge removes an edge from a graph or subgraph.
224
225 Note that an abstract edge has two distinct concrete representations:
226 as an in-edge and as an out-edge. In particular, the pointer as an out-
227 edge is different from the pointer as an in-edge. The function ageqedge
228 canonicalizes the pointers before doing a comparison and so can be used
229 to test edge equality. The sense of an edge can be flipped using agopp.
230
232 Programmer-defined values may be dynamically attached to graphs, sub‐
233 graphs, nodes, and edges. Such values are either character string data
234 (for I/O) or uninterpreted binary records (for implementing algorithms
235 efficiently).
236
238 String attributes are handled automatically in reading and writing
239 graph files. A string attribute is identified by name and by an inter‐
240 nal symbol table entry (Agsym_t) created by Libcgraph. Attributes of
241 nodes, edges, and graphs (with their subgraphs) have separate name‐
242 spaces. The contents of an Agsym_t have a char* name for the attri‐
243 bute's name, a char* defval field for the attribute's default value,
244 and an int id field containing the index of the attribute's specific
245 value for an object in the object's array of attribute values.
246
247 agattr creates or looks up attributes. kind may be AGRAPH, AGNODE, or
248 AGEDGE. If value is (char*)0), the request is to search for an exist‐
249 ing attribute of the given kind and name. Otherwise, if the attribute
250 already exists, its default for creating new objects is set to the
251 given value; if it does not exist, a new attribute is created with the
252 given default, and the default is applied to all pre-existing objects
253 of the given kind. If g is NULL, the default is set for all graphs cre‐
254 ated subsequently. agattrsym is a helper function that looks up an at‐
255 tribute for a graph object given as an argument. agnxtattr permits
256 traversing the list of attributes of a given type. If NULL is passed
257 as an argument it gets the first attribute; otherwise it returns the
258 next one in succession or returns NULL at the end of the list. agget
259 and agset allow fetching and updating a string attribute for an object
260 taking the attribute name as an argument. agxget and agxset do this
261 but with an attribute symbol table entry as an argument (to avoid the
262 cost of the string lookup). Note that agset will fail unless the at‐
263 tribute is first defined using agattr. agsafeset is a convenience
264 function that ensures the given attribute is declared before setting it
265 locally on an object.
266
267 It is sometimes convenient to copy all of the attributes from one ob‐
268 ject to another. This can be done using agcopyattr. This fails and re‐
269 turns non-zero of argument objects are different kinds, or if all of
270 the attributes of the source object have not been declared for the tar‐
271 get object.
272
274 Libcgraph performs its own storage management of strings as reference-
275 counted strings. The caller does not need to dynamically allocate
276 storage.
277
278 agstrdup returns a pointer to a reference-counted copy of the argument
279 string, creating one if necessary. agstrbind returns a pointer to a
280 reference-counted string if it exists, or NULL if not. All uses of
281 cgraph strings need to be freed using agstrfree in order to correctly
282 maintain the reference count.
283
284 The cgraph parser handles HTML-like strings. These should be indistin‐
285 guishable from other strings for most purposes. To create an HTML-like
286 string, use agstrdup_html. The aghtmlstr function can be used to query
287 if a string is an ordinary string or an HTML-like string.
288
289 agcanonStr returns a pointer to a version of the input string canoni‐
290 calized for output for later re-parsing. This includes quoting special
291 characters and keywords. It uses its own internal buffer, so the value
292 will be lost on the next call to agcanonStr. agstrcanon is an unsafe
293 version of agcanonStr, in which the application passes in a buffer as
294 the second argument. Note that the buffer may not be used; if the input
295 string is in canonical form, the function will just return a pointer to
296 it. For both of the functions, the input string must have been created
297 using agstrdup or agstrdup_html. Finally, agcanonStr is identical with
298 agcanonStr except it can be used with any character string. The second
299 argument indicates whether or not the string should be canonicalized as
300 an HTML-like string.
301
303 Uninterpreted records may be attached to graphs, subgraphs, nodes, and
304 edges for efficient operations on values such as marks, weights,
305 counts, and pointers needed by algorithms. Application programmers de‐
306 fine the fields of these records, but they must be declared with a com‐
307 mon header as shown below.
308
309 typedef struct {
310 Agrec_t header;
311 /* programmer-defined fields follow */
312 } user_data_t;
313
314 Records are created and managed by Libcgraph. A programmer must explic‐
315 itly attach them to the objects in a graph, either to individual ob‐
316 jects one at a time via agbindrec, or to all the objects of the same
317 class in a graph via aginit. (Note that for graphs, aginit is applied
318 recursively to the graph and its subgraphs if rec_size is negative (of
319 the actual rec_size.)) The name argument of a record distinguishes
320 various types of records, and is programmer defined (Libcgraph reserves
321 the prefix _ag). If size is 0, the call to agbindrec is simply a
322 lookup. The function aggetrec can also be used for lookup. agdelrec
323 deletes a named record from one object. agclean does the same for all
324 objects of the same class in an entire graph.
325
326 Internally, records are maintained in circular linked lists attached to
327 graph objects. To allow referencing application-dependent data without
328 function calls or search, Libcgraph allows setting and locking the list
329 pointer of a graph, node, or edge on a particular record. This pointer
330 can be obtained with the macro AGDATA(obj). A cast, generally within a
331 macro or inline function, is usually applied to convert the list
332 pointer to an appropriate programmer-defined type.
333
334 To control the setting of this pointer, the move_to_front flag may be
335 TRUE or FALSE. If move_to_front is TRUE, the record will be locked at
336 the head of the list, so it can be accessed directly by AGDATA(obj).
337 The lock can be subsequently released or reset by a call to aggetrec.
338
339
341 (This section is not intended for casual users.) Programmer-defined
342 disciplines customize certain resources- ID namespace, memory, and I/O
343 - needed by Libcgraph. A discipline struct (or NULL) is passed at
344 graph creation time.
345
346 struct Agdisc_s { /* user's discipline */
347 Agmemdisc_t *mem;
348 Agiddisc_t *id;
349 Agiodisc_t *io;
350 } ;
351
352 A default discipline is supplied when NULL is given for any of these
353 fields.
354
355
357 An ID allocator discipline allows a client to control assignment of IDs
358 (uninterpreted integer values) to objects, and possibly how they are
359 mapped to and from strings.
360
361 struct Agiddisc_s { /* object ID allocator */
362 void *(*open) (Agraph_t * g, Agdisc_t*); /* associated with a graph */
363 long (*map) (void *state, int objtype, char *str, unsigned long *id, int createflag);
364 long (*alloc) (void *state, int objtype, unsigned long id);
365 void (*free) (void *state, int objtype, unsigned long id);
366 char *(*print) (void *state, int objtype, unsigned long id);
367 void (*close) (void *state);
368 };
369
370 open permits the ID discipline to initialize any data structures that
371 it maintains per individual graph. Its return value is then passed as
372 the first argument (void *state) to all subsequent ID manager calls.
373
374 alloc informs the ID manager that Libcgraph is attempting to create an
375 object with a specific ID that was given by a client. The ID manager
376 should return TRUE (nonzero) if the ID can be allocated, or FALSE
377 (which aborts the operation).
378
379 free is called to inform the ID manager that the object labeled with
380 the given ID is about to go out of existence.
381
382 map is called to create or look-up IDs by string name (if supported by
383 the ID manager). Returning TRUE (nonzero) in all cases means that the
384 request succeeded (with a valid ID stored through result. There are
385 four cases:
386
387 name != NULL and createflag == 1: This requests mapping a string (e.g.
388 a name in a graph file) into a new ID. If the ID manager can comply,
389 then it stores the result and returns TRUE. It is then also responsi‐
390 ble for being able to print the ID again as a string. Otherwise the ID
391 manager may return FALSE but it must implement the following (at least
392 for graph file reading and writing to work):
393
394 name == NULL and createflag == 1: The ID manager creates a unique new
395 ID of its own choosing. Although it may return FALSE if it does not
396 support anonymous objects, but this is strongly discouraged (to support
397 "local names" in graph files.)
398
399 name != NULL and createflag == 0: This is a namespace probe. If the
400 name was previously mapped into an allocated ID by the ID manager, then
401 the manager must return this ID. Otherwise, the ID manager may either
402 return FALSE, or may store any unallocated ID into result. (This is
403 convenient, for example, if names are known to be digit strings that
404 are directly converted into integer values.)
405
406 name == NULL and createflag == 0: forbidden.
407
408 print is allowed to return a pointer to a static buffer; a caller must
409 copy its value if needed past subsequent calls. NULL should be re‐
410 turned by ID managers that do not map names.
411
412 The map and alloc calls do not pass a pointer to the newly allocated
413 object. If a client needs to install object pointers in a handle ta‐
414 ble, it can obtain them via new object callbacks.
415
417 The I/O discipline provides an abstraction for the reading and writing
418 of graphs.
419 struct Agiodisc_s {
420 int (*fread)(void *chan, char *buf, int bufsize);
421 int (*putstr)(void *chan, char *str);
422 int (*flush)(void *chan); /* sync */
423 } ;
424 Normally, the FILE structure and its related functions are used for
425 I/O. At times, though, an application may need to use a totally differ‐
426 ent type of character source. The associated state or stream informa‐
427 tion is provided by the chan argument to agread or agwrite. The disci‐
428 pline function fread and putstr provide the corresponding functions for
429 read and writing.
430
431
433 Memory management in Libcgraph is handled on a per graph basis using
434 the memory discipline.
435 struct Agmemdisc_s { /* memory allocator */
436 void *(*open)(Agdisc_t*); /* independent of other resources */
437 void *(*alloc)(void *state, size_t req);
438 void *(*resize)(void *state, void *ptr, size_t old, size_t req);
439 void (*free)(void *state, void *ptr);
440 void (*close)(void *state);
441 } ;
442 The open function is used to initialize the memory subsystem, returning
443 state information that is passed to the calls to alloc, resize, and
444 free. The semantics of these should be comparable to the standard C
445 library functions malloc, realloc, and free, except that new space cre‐
446 ated by agalloc and agrealloc should be zeroed out. The close function
447 is used to terminate the memory subsystem, freeing any additional open
448 resources. For actual allocation, the library uses the functions agal‐
449 loc, agrealloc, and agfree, which provide simple wrappers for the un‐
450 derlying discipline functions alloc, resize, and free.
451
452 When Libcgraph is compiled with Vmalloc (which is not the default),
453 each graph has its own heap. Programmers may allocate application-de‐
454 pendent data within the same heap as the rest of the graph. The advan‐
455 tage is that a graph can be deleted by atomically freeing its entire
456 heap without scanning each individual node and edge.
457
458
460 An Agcbdisc_t defines callbacks to be invoked by Libcgraph when ini‐
461 tializing, modifying, or finalizing graph objects. Disciplines are
462 kept on a stack. Libcgraph automatically calls the methods on the
463 stack, top-down. Callbacks are installed with agpushdisc, uninstalled
464 with agpopdisc, and can be held pending or released via agcallbacks.
465
467 agroot takes any graph object (graph, subgraph, node, edge) and returns
468 the root graph in which it lives. agraphof does the same, except it is
469 the identity function on graphs and subgraphs. Note that there is no
470 function to return the least subgraph containing an object, in part be‐
471 cause this is not well-defined as nodes and edges may be in incompara‐
472 ble subgraphs.
473
474 agcontains(g,obj) returns non-zero if obj is a member of (sub)graph g.
475 agdelete(g,obj) is equivalent to agclose, agdelnode, and agdeledge for
476 obj being a graph, node or edge, respectively. It returns -1 if obj
477 does not belong to g.
478
479 AGDATA, AGID, and AGTYPE are macros returning the specified fields of
480 the argument object. The first is described in the RECORDS section
481 above. The second returns the unique integer ID associated with the ob‐
482 ject. The last returns AGRAPH, AGNODE, and AGEDGE depending on the type
483 of the object.
484
485 agnameof returns a string descriptor for the object. It returns the
486 name of the node or graph, and the key of an edge. agobjkind is a syn‐
487 onym for AGTYPE.
488
489
491 The library provides a variety of mechanisms to control the reporting
492 of errors and warnings. At present, there are basically two types of
493 messages: warnings and errors. A message is only written if its type
494 has higher priority than a programmer-controlled minimum, which is AG‐
495 WARN by default. The programmer can set this value using agseterr,
496 which returns the previous value. Calling agseterr(AGMAX) turns off the
497 writing of messages.
498
499 The function agerr if the main entry point for reporting an anomaly.
500 The first argument indicates the type of message. Usually, the first
501 argument in AGWARN or AGERR to indicate warnings and errors, respec‐
502 tively. Sometimes additional context information is only available in
503 functions calling the function where the error is actually caught. In
504 this case, the calling function can indicate that it is continuing the
505 current error by using AGPREV as the first argument. The remaining ar‐
506 guments to agerr are the same as the arguments to printf.
507
508 The functions agwarningf and agerrorf are shorthand for
509 agerr(AGERR,...) and agerr(AGWARN,...), respectively.
510
511 Some applications desire to directly control the writing of messages.
512 Such an application can use the function agseterrf to register the
513 function that the library should call to actually write the message.
514 The previous error function is returned. By default, the message is
515 written to stderr.
516
517 Errors not written are stored in a log file. The last recorded error
518 can be retreived by calling aglasterr.
519
520 The function agerrors returns non-zero if errors have been reported.
521
523 #include <stdio.h>
524 #include <cgraph.h>
525
526 typedef struct {Agrec_t hdr; int x,y,z;} mydata;
527
528 void main(int argc, char **argv)
529 {
530 Agraph_t *g, *h;
531 Agnode_t *v;
532 Agedge_t *e;
533 Agsym_t *attr;
534 Dict_t *d;
535 int cnt;
536 mydata *p;
537
538 if (g = agread(stdin,NIL(Agdisc_t*))) {
539 cnt = 0; attr = 0;
540 while (attr = agnxtattr(g, AGNODE, attr)) cnt++;
541 printf("The graph %s has %d attributes\n",agnameof(g),cnt);
542
543 /* make the graph have a node color attribute, default is blue */
544 attr = agattr(g,AGNODE,"color","blue");
545
546 /* create a new graph of the same kind as g */
547 h = agopen("tmp",g->desc, NULL);
548
549 /* this is a way of counting all the edges of the graph */
550 cnt = 0;
551 for (v = agfstnode(g); v; v = agnxtnode(g,v))
552 for (e = agfstout(g,v); e; e = agnxtout(g,e))
553 cnt++;
554
555 /* attach records to edges */
556 for (v = agfstnode(g); v; v = agnxtnode(g,v))
557 for (e = agfstout(g,v); e; e = agnxtout(g,e)) {
558 p = (mydata*) agbindrec(e,"mydata",sizeof(mydata),TRUE);
559 p->x = 27; /* meaningless data access example */
560 ((mydata*)(AGDATA(e)))->y = 999; /* another example */
561 }
562 }
563 }
564
565
567 digraph G {
568 a -> b;
569 c [shape=box];
570 a -> c [weight=29,label="some text"];
571 subgraph anything {
572 /* the following affects only x,y,z */
573 node [shape=circle];
574 a; x; y -> z; y -> z; /* multiple edges */
575 }
576 }
577
578 strict graph H {
579 n0 -- n1 -- n2 -- n0; /* a cycle */
580 n0 -- {a b c d}; /* a star */
581 n0 -- n3;
582 n0 -- n3 [weight=1]; /* same edge because graph is strict */
583 }
584
586 Libcdt(3)
587
588
590 It is difficult to change endpoints of edges, delete string attributes
591 or modify edge keys. The work-around is to create a new object and
592 copy the contents of an old one (but new object obviously has a differ‐
593 ent ID, internal address, and object creation timestamp).
594
595 The API lacks convenient functions to substitute programmer-defined or‐
596 dering of nodes and edges but in principle this can be supported.
597
598 The library is not thread safe.
599
601 Stephen North, north@research.att.com, AT&T Research.
602
603
604
605 28 FEBRUARY 2013 LIBCGRAPH(3)