.ds Vv 1.2.14 .ds wd [a\-zA\-Z0\-9_.+\-]+ .TH VistaIOattribute 3 "28 January 1994" "VistaIO Version \*(Vv" .SH NAME VistaIOattribute \- representation of a list of name/value pairs .SH SYNOPSIS .B VistaIOAttrList \fIlist\fP; .PP .B VistaIOAttrListPosn \fIposn\fP; .SH DESCRIPTION .SS Introduction An attribute associates a value with a name. Generally, various properties of an object such as an image are described by attributes, each naming one property and specifying that property's associated value. Attributes are collected into lists, and Vista library routines are available for accessing and manipulating these lists. A list is referred to by a pointer of type \fBVistaIOAttrList\fP. .PP The attribute list representation is closely related to the Vista data file format. Among other things, attribute lists can represent in memory the contents of Vista data files. .PP An attribute's name is an alphanumeric string \(em specifically, a sequence of characters matching the regular expression \*(wd. (Regular expressions are described in \fBgrep\fP(1).) Attribute names are represented in memory as null-terminated character strings. They may be 50 character in length. .PP An attribute's value may be a character string, a (nested) attribute list, or a pointer to data of a specified type. .RS 2n .IP \(bu 2n If it's a character string, the string may optionally be interpreted as an number whenever it is accessed. Library routines exist, for example, that can return a string's value as a \fBVistaIOShort\fP, or set it with a \fBVistaIOFloat\fP value. The following representations can be used when accessing character-string attribute values: \fBVistaIOBit\fP, \fBVistaIOUByte\fP, \fBVistaIOSByte\fP, \fBVistaIOShort\fP, \fBVistaIOLong\fP, \fBVistaIOFloat\fP, \fBVistaIODouble\fP, \fBVistaIOBoolean\fP, or \fBVistaIOString\fP. An error will be signalled if an attempt is made to obtain an attribute's value in a representation to which it cannot be converted. .IP A character-string attribute value can also be interpreted as a keyword. Again, conversion between keywords and any desired representation occurs when the attribute value is accessed. The routines you use to access attribute values allow you to specify an optional dictionary that describes a mapping between keywords and values. The form of this dictionary is described by the \fBVistaIOdictionary\fP(3) manual page. Using a dictionary, for example, you can fetch an attribute's value as a \fBVistaIOBoolean\fP while converting the keywords \fBfalse\fP and \fBtrue\fP to the values 0 and 1. .IP \(bu An attribute's value may be another attribute list. However, circular references, as when an attribute list is the value of one of its attributes, are not allowed. .IP \(bu An attribute's value may be an object with any of the standard object types (e.g., an image or edge set); or it may be an object of a type that has been registered by the programmer using the mechanism described in \fBVistaIOtype\fP(3). Because they are registered, such types are automatically read from data files and written to data files by library routines such as \fBVistaIOReadFile\fP(3) and \fBVistaIOWriteFile\fP(3). .IP \(bu An attribute's value may be of type \fBVistaIOBundle\fP, described in \fBVistaIOBundle\fP(3). A \fBVistaIOBundle\fP can represent an object whose type has not been registered with the \fBVistaIOtype\fP(3) mechanism, in a way that allows the object to be copied unchanged from an input data file to an output data file. It's used to represent objects of unknown type encountered in input data files. .IP \(bu An attribute's value may be a pointer to an opaque data structure. Such a pointer is of type \fBVistaIOPointer\fP. Library routines only allow for getting and setting a \fBVistaIOPointer\fP attribute value; they cannot read \fBVistaIOPointer\fP values from data files, or write them to data files. .RE .PP The elements of an attribute list may be accessed by attribute name, in which case each element should have a unique name and the order of attributes within the list is not significant. In this form of access the attribute list is treated as a set. Alternatively, the elements of an attribute list may be accessed by their position within the list, in which case attribute names needn't be unique and the ordering of list elements is significant. In this form of access the attribute list is treated as a sequence. The library provides support for both forms of access. .PP A position within an attribute list is identified by a structure of type \fBVistaIOAttrListPosn\fP. Its value can denote a particular attribute within a list, or no attribute (analogous to .SB NULL\c . .SS "Creating, Copying, and Destroying Attribute Lists" The following routines will create, copy, and destroy attribute lists. .PP .B VistaIOAttrList VistaIOCreateAttrList (void) .IP \fBVistaIOCreateAttrList\fP creates and returns an empty attribute list. .PP .B VistaIOAttrList VistaIOCopyAttrList (VistaIOAttrList \fIlist\fP) .IP \fBVistaIOCopyAttrList\fP generates a complete copy of \fIlist\fP using newly-allocated storage for each list element. The new list contains its own copy of each attribute value \(em except that for a \fBVistaIOPointer\fP value, the pointer is copied but not the (opaque) data structure to which it points. .PP .B void VistaIODestroyAttrList (VistaIOAttrList \fIlist\fP) .IP \fBVistaIODestroyAttrList\fP releases the storage occupied by \fIlist\fP. Also released is storage occupied by attribute values \(em except that for a \fBVistaIOPointer\fP value, the pointer is released but not the (opaque) data structure to which it points. .SS "Traversing an Attribute List" The following macros are used to sequence through an attribute list in either direction. They are appropriate when accessing an attribute list representing a sequence (as opposed to a set) of attributes. .PP .B void VistaIOFirstAttr (VistaIOAttrList \fIlist\fP, VistaIOAttrListPosn *\fIposn\fP) .IP \fBVistaIOFirstAttr\fP sets \fIposn\fP to point to the first attribute in \fIlist\fP. If the list is empty, \fIposn\fP is set to point to nothing (a condition that can be tested using the \fBVistaIOAttrExists\fP macro). .PP .B void VistaIOLastAttr (VistaIOAttrList \fIlist\fP, VistaIOAttrListPosn *\fIposn\fP) .IP \fBVistaIOLastAttr\fP sets \fIposn\fP to point to the last attribute in \fIlist\fP. If the list is empty, \fIposn\fP is set to point to nothing (a condition that can be tested using the \fBVistaIOAttrExists\fP macro). .PP .B void VistaIONextAttr (VistaIOAttrListPosn *\fIposn\fP) .IP \fBVistaIONextAttr\fP sets \fIposn\fP to point to the next attribute in its list. If \fIposn\fP already points to the list's last attribute, \fIposn\fP is set to point to nothing (a condition that can be detected by the \fBVistaIOAttrExists\fP macro). .PP .B void VistaIOPrevAttr (VistaIOAttrList \fIlist\fP, VistaIOAttrListPosn *\fIposn\fP) .IP \fBVistaIOPrevAttr\fP sets \fIposn\fP to point to the previous attribute in its list. If \fIposn\fP already points to the list's first attribute, \fIposn\fP is set to point to nothing (a condition that can be detected by the \fBVistaIOAttrExists\fP macro). .PP .B VistaIOBoolean VistaIOAttrExists (VistaIOAttrListPosn *\fIposn\fP) .IP \fBVistaIOAttrExists\fP returns .SB TRUE if \fIposn\fP points to an attribute, and .SB FALSE if it points to nothing. This macro is used, for example, to test for the end of an attribute list while sequencing through it. .PP .B VistaIOBoolean VistaIOAttrListEmpty (VistaIOAttrList *\fIlist\fP) .IP \fBVistaIOAttrListEmpty\fP returns .SB TRUE if \fIlist\fP is empty. .SS "Accessing Attributes by Position" The following macros and routines access the attribute at a specified position within an attribute list. .PP .B VistaIOStringConst VistaIOGetAttrName (VistaIOAttrListPosn *\fIposn\fP) .IP The \fBVistaIOGetAttrName\fP macro returns the name of the attribute at \fIposn\fP. .PP .B VistaIORepnKind VistaIOGetAttrRepn (VistaIOAttrListPosn *\fIposn\fP) .IP The \fBVistaIOGetAttrRepn\fP macro returns the type of representation of the attribute value at \fIposn\fP. .HP 10n .na .nh .B VistaIOBoolean VistaIOGetAttrValue (VistaIOAttrListPosn\ *\fIposn\fP, .B VistaIODictEntry\ *\fIdict\fP, VistaIORepnKind\ \fIrepn\fP, VistaIOPointer\ \fIvalue\fP) .ad .hy .IP "" 0.5i This routine gets the value of the attribute at \fIposn\fP. (See \fBVistaIOGetAttrValue\fP(3) for details.) .HP 10n .na .nh .B void VistaIOSetAttrValue (VistaIOAttrListPosn\ *\fIposn\fP, .B VistaIODictEntry\ *\fIdict\fP, VistaIORepnKind\ \fIrepn\fP, \fItype\ value\fP) .ad .hy .IP "" 0.5i This routine sets the value of the attribute at \fIposn\fP. (See \fBVistaIOSetAttrValue\fP(3) for details.) .SS "Accessing Attributes by Name" The following routines access attributes by name. They are appropriate when accessing an attribute list representing a set of attributes, in which each attribute name is present at most once. .HP 10n .na .nh .B VistaIOBoolean VistaIOLookupAttr (VistaIOAttrList \fIlist\fP, VistaIOStringConst\ \fIname\fP, .B VistaIOAttrListPosn\ *\fIposn\fP) .ad .hy .IP "" 0.5i \fBVistaIOLookupAttr\fP locates the first attribute named \fIname\fP in the list \fIlist\fP. If the attribute is found, .SB TRUE is returned along with the attribute's position in \fIposn\fP. Otherwise .SB FALSE is returned. .HP 10n .na .nh .B VistaIOGetAttrResult VistaIOGetAttr (VistaIOAttrList\ *\fIlist\fP, .B VistaIOStringConst\ \fIname\fP, VistaIODictEntry\ *\fIdict\fP, .B VistaIORepnKind\ \fIrepn\fP, VistaIOPointer\ \fIvalue\fP) .ad .hy .IP "" 0.5i \fBVistaIOGetAttr\fP gets the value of the named attribute. (See \fBVistaIOGetAttr\fP(3) for details.) .HP 10n .na .nh .B void VistaIOSetAttr (VistaIOAttrList\ *\fIlist\fP, .B VistaIOStringConst\ \fIname\fP, VistaIODictEntry\ *\fIdict\fP, .B VistaIORepnKind\ \fIrepn\fP, \fItype\ value\fP) .ad .hy .IP "" 0.5i \fBVistaIOSetAttr\fP sets the value of the named attribute, creating an attribute if the list doesn't already contain one with that name. (See \fBVistaIOSetAttr\fP(3) for details.) .SS "Inserting and Deleting Attributes" The following routines add attributes to lists and remove them. .HP 10n .na .nh .B void VistaIOInsertAttr (VistaIOAttrListPosn *\fIposn\fP, VistaIOBoolean\ \fIafter\fP, .B VistaIOStringConst\ \fIname\fP, VistaIODictEntry\ *\fIdict\fP, .B VistaIORepnKind\ \fIrepn\fP, \fItype\ value\fP) .ad .hy .IP "" 0.5i \fBVistaIOInsertAttr\fP inserts an attribute before or after a specified position within an attribute list. (See \fBVistaIOInsertAttr\fP(3) for details.) .PP .B void VistaIODeleteAttr (VistaIOAttrListPosn *\fIposn\fP) .IP \fBVistaIODeleteAttr\fP deletes the attribute at \fIposn\fP. It leaves \fIposn\fP pointing to the following attribute if their is one, or nothing if the attribute deleted was the last on its list. .HP 10n .na .nh .B void VistaIOAppendAttr (VistaIOAttrList *\fIlist\fP, .B VistaIOStringConst\ \fIname\fP, VistaIODictEntry\ *\fIdict\fP, .B VistaIORepnKind\ \fIrepn\fP, \fItype\ value\fP) .ad .hy .IP "" 0.5i \fBVistaIOAppendAttr\fP appends an attribute to the back of \fIlist\fP. (See \fBVistaIOAppendAttr\fP(3) for details.) .HP 10n .na .nh .B void VistaIOPrependAttr (VistaIOAttrList *\fIlist\fP, .B VistaIOStringConst\ \fIname\fP, VistaIODictEntry\ *\fIdict\fP, .B VistaIORepnKind\ \fIrepn\fP, \fItype\ value\fP) .ad .hy .IP "" 0.5i \fBVistaIOPrependAttr\fP prepends an attribute to the front of \fIlist\fP. (See \fBVistaIOPrependAttr\fP(3) for details.) .HP 10n .na .nh .B VistaIOBoolean VistaIOExtractAttr (VistaIOAttrList *\fIlist\fP, .B VistaIOStringConst\ \fIname\fP, VistaIODictEntry\ *\fIdict\fP, .B VistaIORepnKind\ \fIrepn\fP, VistaIOPointer\ \fIvalue\fP, .B VistaIOBoolean\ \fIrequired\fP) .ad .hy .IP "" 0.5i \fBVistaIOExtractAttr\fP locates an attribute named \fIname\fP in \fIlist\fP, removing it if found and returning its value. (See \fBVistaIOExtractAttr\fP(3) for details.) .SS "Encoding and Decoding Attribute VistaIOalues" The following routines translate character-string attribute values to and from other representations. .HP 10n .na .nh .B VistaIOStringConst VistaIOEncodeAttrValue (VistaIODictEntry\ *\fIdict\fP, .B VistaIORepnKind\ \fIrepn\fP, \fItype\ value\fP) .ad .hy .IP "" 0.5i \fBVistaIOEncodeAttrValue\fP takes a value and an optional dictionary, and encodes the value as a character string suitable for storage in an attribute list or output to a data file. (See \fBVistaIOEncodeAttrValue\fP(3) for details.) .HP 10n .na .nh .B VistaIOBoolean VistaIODecodeAttrValue (VistaIOStringConst \fIstr\fP, .B VistaIODictEntry\ *\fIdict\fP, .B VistaIORepnKind\ \fIrepn\fP, VistaIOPointer\ \fIvalue\fP) .ad .hy .IP "" 0.5i \fBVistaIODecodeAttrValue\fP performs the inverse operation, taking a string and returning a value in the requested representation. (See \fBVistaIODecodeAttrValue\fP(3) for details.) .SS "Inputting and Outputting Attribute Lists" The following routines read and write attribute lists. .PP .B VistaIOAttrList VistaIOReadFile (FILE *\fIfile\fP, VistaIOBoolean (*\fIfilter\fP) ()) .IP \fBVistaIOReadFile\fP reads an entire data file, returning it as an attribute list. (See \fBVistaIOReadFile\fP(3) for details.) .PP .B VistaIOBoolean VistaIOWriteFile (FILE *\fIfile\fP, VistaIOAttrList\ \fIlist\fP) .IP \fBVistaIOWriteFile\fP writes an entire data file with the contents of an attribute list. (See \fBVistaIOWriteFile\fP(3) for details.) .SS "Storage Management" To program with attribute lists it is necessary to know something about how storage is managed for attribute values. The general rule is that when individual attributes are accessed, values aren't created, copied, or destroyed \(em only references to them are manipulated. On the other hand when an entire attribute list is create, copied, or destroyed, then all the values will be created, copied, or destroyed along with it. Unfortunately, the exact behavior must depend on both the type of value an attribute has, and the type of operation being performed with the attribute. The following table summarizes the various cases. .RS 2n .PP For an attribute whose value is a character string: .RS 2n .IP \(bu 2n The value is stored in an attribute list as a string. .IP \(bu \fBVistaIOCopyAttrList\fP creates a new copy of the string for the list it creates. .IP \(bu \fBVistaIODestroyAttrList\fP releases storage occupied by the string when it destroys the list containing the attribute. .IP \(bu \fBVistaIOGetAttr\fP and \fBVistaIOGetAttrValue\fP return a pointer to a shared copy of the string. This pointer is valid until the attribute is modified. .IP \(bu When \fBVistaIOSetAttr\fP, \fBVistaIOSetAttrValue\fP, \fBVistaIODeleteAttr\fP, or \fBVistaIOExtractAttr\fP modifies or deletes an attribute with a string value, it releases the storage occupied by that value. .IP \(bu When \fBVistaIOSetAttr\fP or \fBVistaIOSetAttrValue\fP sets an attribute to a new string value, it stores its own copy of the string in the attribute list. .RE .PP For an attribute whose value is an attribute list, object, or \fBVistaIOBundle\fP: .RS 2n .IP \(bu 2n The value is stored in an attribute list as a pointer. .IP \(bu \fBVistaIOCopyAttrList\fP creates a new copy of the value for the list it creates. (If the value is an attribute list, for example, it calls itself recursively to clone the value.) .IP \(bu \fBVistaIODestroyAttrList\fP releases storage occupied by the value when it destroys the list containing the attribute. .IP \(bu \fBVistaIOGetAttr\fP and \fBVistaIOGetAttrValue\fP return a pointer to a shared copy of the value (they don't make a new copy to return). This pointer is valid until the value is explicitly destroyed, or indirectly destroyed by destroying the list containing the attribute. .IP \(bu When \fBVistaIOSetAttr\fP, \fBVistaIOSetAttrValue\fP, \fBVistaIODeleteAttr\fP, or \fBVistaIOExtractAttr\fP modifies or deletes an attribute with one of these values, it discards the pointer to the value but not the value itself. .IP \(bu When \fBVistaIOSetAttr\fP or \fBVistaIOSetAttrValue\fP sets an attribute to one of these values, it stores a copy of a pointer to the value, but it doesn't copy the value itself. .RE .PP For an attribute whose value is a \fBVistaIOPointer\fP: .RS 2n .IP \(bu 2n The value is stored in an attribute list as a pointer. .IP \(bu \fBVistaIOCopyAttrList\fP creates a new copy of the pointer for the list it creates, but it doesn't copy the (opaque) data structure pointed to. .IP \(bu \fBVistaIODestroyAttrList\fP doesn't release the (opaque) data structure pointed to when it destroys the list containing the attribute. .IP \(bu \fBVistaIOGetAttr\fP and \fBVistaIOGetAttrValue\fP simply return the pointer. .IP \(bu When \fBVistaIOSetAttr\fP, \fBVistaIOSetAttrValue\fP, \fBVistaIODeleteAttr\fP, or \fBVistaIOExtractAttr\fP modifies or deletes an attribute with one of these values, it discards the old pointer value but doesn't release the (opaque) data structure it points to. .IP \(bu When \fBVistaIOSetAttr\fP or \fBVistaIOSetAttrValue\fP sets an attribute to one of these values, it records the new pointer value, but it doesn't copy the (opaque) data structure it points to. .RE .RE .SS "Data Structures" .ta 20n .nf .B typedef struct _VAttrRec { .RS .ft B VistaIOAttrRec *next; /* next in list */ VistaIOAttrRec *prev; /* previous in list */ VistaIORepnKind repn; /* rep'n of attribute value */ VistaIOPointer value; /* pointer to attribute value */ char name[1]; /* beginning of name string */ .ft .RE .B } VistaIOAttrRec, *VistaIOAttrList; .RE .fi .PP .nf .B typedef struct { .RS .ft B VistaIOAttrList list; /* the list */ VistaIOAttrRec *ptr; /* position within the list */ .ft .RE .B } VistaIOAttrListPosn; .fi .DT .PP Programmers using attribute lists will usually not need to access components of the attribute list data structure directly from their code since there are library routines and macros available for most purposes. However, when debugging, one may occasionally need to examine an attribute list directly. .PP In a list of attributes, each attribute is represented by a \fBVistaIOAttrRec\fP record. Records are allocated with a variable size sufficient to contain the attribute name and, if the attribute value is stored as a character string, the attribute value also. .PP The record's \fBname\fP field is a variable-length character array containing the attribute's name terminated by a .SB NULL character. The \fBrepn\fP field specifies whether the attribute's value is stored as a character string (\fBVistaIOStringRepn\fP), an attribute list (\fBVistaIOAttrListRepn\fP), a pointer to an opaque data structure (\fBVistaIOPointerRepn\fP), or some other object type (\fBVistaIOBundle\fP, \fBVistaIOImage\fP, \fBVistaIOEdges\fP, etc.). Accordingly, the \fBvalue\fP field will point to a null-terminated character string, an attribute list, an opaque data structure, a \fBVistaIOBundleRec\fP structure, etc. If the value is a string, that string immediately follows the name string in the variable length record. The \fBnext\fP and \fBprev\fP fields form a doubly-linked list, with .SB NULL pointers marking the list's ends. .PP An attribute list contains, in addition to a \fBVistaIOAttrRec\fP record for each of its attributes, one \fBVistaIOAttrRec\fP record serving as a list header. The only significant fields of this header record are the \fBnext\fP and \fBprev\fP fields, which point to the first and last attributes of the list. An attribute list is of type \fBVistaIOAttrList\fP, which is a pointer to the list's header record. .PP The library includes routines and macros that allow one to step through an attribute list, and to access an attribute by its position in a list. These employ the \fBVistaIOAttrListPosn\fP type, which acts as a pointer to a particular attribute within a list. The \fBVistaIOAttrListPosn\fP's \fBlist\fP field identifies an entire list, and its \fBptr\fP field refers to a specific attribute within that list. .SH EXAMPLES .ta 4n 8n 12n 16n The examples in this section assume the following variables: .PP .RS .nf .ft B VistaIOAttrList list; VistaIOAttrListPosn posn; VistaIOImage image, result; .ft .fi .RE .PP This code fragment creates an attribute list, sets some attributes in it, writes the list to the standard output stream, and finally destroys the list. .PP .RS .nf .ft B list = VistaIOCreateAttrList (); VistaIOSetAttr (list, "name", NULL, VistaIOStringRepn, "Socrates"); VistaIOSetAttr (list, "comment", NULL, VistaIOStringRepn, "Greek philosopher"); VistaIOSetAttr (list, "age", NULL, VistaIOShortRepn, (VistaIOShort) 37); VistaIOWriteFile (stdout, list); VistaIODestroyAttrList (list); .fi .RE .PP This reads an attribute list from the standard input stream and prints the name of each of its attributes in sequence: .PP .RS .nf .ft B list = VistaIOReadFile (stdin, NULL); for (VistaIOFirstAttr (list, & posn); VistaIOAttrExists (& posn); VistaIONextAttr (& posn)) printf ("%s\\n", VistaIOGetAttrName (& posn)); .fi .RE .PP To add a series of images to an attribute list: .PP .RS .nf .ft B while (...) { image = VistaIOCreateImage (...); VistaIOAppendAttr (list, ..., VistaIOImageRepn, image); /* Note: don't discard image. */ } .fi .RE .PP To modify each image in an attribute list without replacing it: .PP .RS .nf .ft B for (VistaIOFirstAttr (list, & posn); VistaIOAttrExists (& posn); VistaIONextAttr (& posn)) { if (VistaIOGetAttrRepn (& posn) != VistaIOImageRepn) continue; VistaIOGetAttrValue (& posn, NULL, VistaIOImageRepn, & image); ProcessImage (image, image, ...); /* Note: modifications to image are inherited by the attribute. */ } .fi .RE .PP To replace each image in an attribute list: .PP .RS .nf .ft B for (VistaIOFirstAttr (list, & posn); VistaIOAttrExists (& posn); VistaIONextAttr (& posn)) { if (VistaIOGetAttrRepn (& posn) != VistaIOImageRepn) continue; VistaIOGetAttrValue (& posn, NULL, VistaIOImageRepn, & image); result = ProcessImage (image, NULL, ...); VistaIOSetAttrValue (& posn, NULL, VistaIOImageRepn, result); /* Note: the attribute now refers to result, not image. */ VistaIODestroyImage (image); } .fi .RE .PP To delete a named image from an attribute list: .PP .RS .nf .ft B if (VistaIOLookupAttr (list, "...", & posn)) { VistaIOGetAttrValue (& posn, NULL, VistaIOImageRepn, & image); VistaIODeleteAttr (& posn); VistaIODestroyImage (image); } .fi .RE .DT .SH "SEE ALSO" .nh .na .BR VistaIOBundle (3), .BR VistaIOdictionary (3), .BR VistaIOtype (3), , .br .BR VistaIOGetAttrValue (3), .BR VistaIOSetAttrValue (3), .BR VistaIOGetAttr (3), .BR VistaIOSetAttr (3), .br .BR VistaIOInsertAttr (3), .BR VistaIOAppendAttr (3), .BR VistaIOPrependAttr (3), .BR VistaIOExtractAttr (3), .br .BR VistaIOEncodeAttrValue (3), .BR VistaIODecodeAttrValue (3), .br .BR VistaIOReadFile (3), .BR VistaIOWriteFile (3) .hy .ad .SH AUTHOR Art Pope Adaption to vistaio: Gert Wollny