| 1 | .\" -*-nroff-*- |
| 2 | .de VS |
| 3 | .sp 1 |
| 4 | .RS |
| 5 | .nf |
| 6 | .ft B |
| 7 | .. |
| 8 | .de VE |
| 9 | .ft R |
| 10 | .fi |
| 11 | .RE |
| 12 | .sp 1 |
| 13 | .. |
| 14 | .TH assoc 3 "23 January 2001" "Straylight/Edgeware" "mLib utilities library" |
| 15 | .SH NAME |
| 16 | assoc \- tables indexed by atoms |
| 17 | .\" @assoc_create |
| 18 | .\" @assoc_destroy |
| 19 | .\" @assoc_find |
| 20 | .\" @assoc_remove |
| 21 | .\" @assoc_mkiter |
| 22 | .\" @assoc_next |
| 23 | .\" |
| 24 | .\" @ASSOC_ATOM |
| 25 | .\" |
| 26 | .SH SYNOPSIS |
| 27 | .nf |
| 28 | .B "#include <mLib/assoc.h>" |
| 29 | |
| 30 | .BI "void assoc_create(assoc_table *" t ); |
| 31 | .BI "void assoc_destroy(assoc_table *" t ); |
| 32 | |
| 33 | .BI "void *assoc_find(assoc_table *" t ", atom *" a ", size_t " sz ", unsigned *" f ); |
| 34 | .BI "void assoc_remove(assoc_table *" t ", void *" b ); |
| 35 | |
| 36 | .BI "atom *ASSOC_ATOM(const void *" p ); |
| 37 | |
| 38 | .BI "void assoc_mkiter(assoc_iter *" i ", assoc_table *" t ); |
| 39 | .BI "void *assoc_next(assoc_iter *" i ); |
| 40 | .fi |
| 41 | .SH DESCRIPTION |
| 42 | An |
| 43 | .I "association table" |
| 44 | is a data structure which maps atoms (see |
| 45 | .BR atom (3)) |
| 46 | to arbitrary values. It works in a similar way to the symbol tables |
| 47 | implemented by |
| 48 | .BR sym (3), |
| 49 | except that it uses atoms rather than blocks of data as keys. |
| 50 | .PP |
| 51 | Like |
| 52 | .BR sym (3), |
| 53 | it implements an |
| 54 | .I intrusive |
| 55 | table: the value structures must include an |
| 56 | .B assoc_base |
| 57 | structure. |
| 58 | .PP |
| 59 | There are three main data structures: |
| 60 | .TP |
| 61 | .B assoc_table |
| 62 | Keeps track of the information associated with a particular table. |
| 63 | .TP |
| 64 | .B assoc_base |
| 65 | The header which must be attached to the front of all the value objects. |
| 66 | .TP |
| 67 | .B assoc_iter |
| 68 | An iterator object, used for enumerating all of the associations stored |
| 69 | in the table |
| 70 | .PP |
| 71 | All of the above structures should be considered |
| 72 | .IR opaque : |
| 73 | don't try looking inside. |
| 74 | .SS "Creation and destruction" |
| 75 | The |
| 76 | .B assoc_table |
| 77 | object itself needs to be allocated by the caller. It is initialized by |
| 78 | passing it to the function |
| 79 | .BR assoc_create . |
| 80 | After initialization, the table contains no entries. |
| 81 | .PP |
| 82 | Initializing an association table involves allocating some memory. If |
| 83 | this allocation fails, an |
| 84 | .B EXC_NOMEM |
| 85 | exception is raised. |
| 86 | .PP |
| 87 | When an association table is no longer needed, the memory occupied by |
| 88 | the values and other maintenance structures can be reclaimed by calling |
| 89 | .BR assoc_destroy . |
| 90 | Any bits of user data attached to values should previously have been |
| 91 | destroyed. |
| 92 | .SS "Adding, searching and removing" |
| 93 | Most of the actual work is done by the function |
| 94 | .BR assoc_find . |
| 95 | It does both lookup and creation, depending on its arguments. To do its |
| 96 | job, it needs to know the following bits of information: |
| 97 | .TP |
| 98 | .BI "assoc_table *" t |
| 99 | A pointer to an association table to manipulate. |
| 100 | .TP |
| 101 | .BI "atom *" a |
| 102 | The address of the atom to use as a key. |
| 103 | .TP |
| 104 | .BI "size_t " sz |
| 105 | The size of the value block to allocate if the key could not be found. |
| 106 | If this is zero, no value is allocated, and a null pointer is returned |
| 107 | to indicate an unsuccessful lookup. |
| 108 | .TP |
| 109 | .BI "unsigned *" f |
| 110 | The address of a `found' flag to set. This is an output parameter. On |
| 111 | exit, |
| 112 | .B assoc_find |
| 113 | will set the value of |
| 114 | .BI * f |
| 115 | to zero if the key could not be found, or nonzero if it was found. This |
| 116 | can be used to tell whether the value returned has been newly allocated, |
| 117 | or whether it was already in the table. |
| 118 | .PP |
| 119 | A symbol can be removed from the table by calling |
| 120 | .BR assoc_remove , |
| 121 | passing the association table itself, and the value block that needs |
| 122 | removing. |
| 123 | .SS "Enquiries about associations" |
| 124 | Given a pointer |
| 125 | .I a |
| 126 | to an association, the expression |
| 127 | .BI ASSOC_ATOM( a ) |
| 128 | has as its value a poinetr to the atom which is that association's key. |
| 129 | .SS "Enumerating associations" |
| 130 | Enumerating the values in an association table is fairly simple. |
| 131 | Allocate an |
| 132 | .B assoc_iter |
| 133 | object from somewhere. Attach it to an association table by calling |
| 134 | .BR assoc_mkiter , |
| 135 | and passing in the addresses of the iterator and the symbol table. |
| 136 | Then, each call to |
| 137 | .B assoc_next |
| 138 | will return a different value from the association table, until all of |
| 139 | them have been enumerated, at which point, |
| 140 | .B assoc_next |
| 141 | returns a null pointer. |
| 142 | .PP |
| 143 | It's safe to remove the symbol you've just been returned by |
| 144 | .BR assoc_next . |
| 145 | However, it's not safe to remove any other symbol. So don't do that. |
| 146 | .PP |
| 147 | When you've finished with an iterator, it's safe to just throw it away. |
| 148 | You don't need to call any functions beforehand. |
| 149 | .SH SEE ALSO |
| 150 | .BR atom (3), |
| 151 | .BR hash (3), |
| 152 | .BR sym (3), |
| 153 | .BR mLib (3). |
| 154 | .SH AUTHOR |
| 155 | Mark Wooding, <mdw@distorted.org.uk> |