| 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 atom 3 "21 January 2001" mLib |
| 15 | .SH NAME |
| 16 | atom \- atom table manager |
| 17 | .\" @atom_createtable |
| 18 | .\" @atom_destroytable |
| 19 | .\" @atom_intern |
| 20 | .\" @atom_nintern |
| 21 | .\" @atom_gensym |
| 22 | .\" @atom_name |
| 23 | .\" @atom_len |
| 24 | .\" @atom_hash |
| 25 | .\" @atom_mkiter |
| 26 | .\" @atom_next |
| 27 | .\" |
| 28 | .\" @ATOM_GLOBAL |
| 29 | .\" @INTERN |
| 30 | .\" @GENSYM |
| 31 | .\" @ATOM_NAME |
| 32 | .\" @ATOM_LEN |
| 33 | .\" @ATOM_HASH |
| 34 | .\" |
| 35 | .SH SYNOPSIS |
| 36 | .nf |
| 37 | .B "#include <mLib/atom.h>" |
| 38 | |
| 39 | .BI "void atom_createtable(atom_table *" t ); |
| 40 | .BI "void atom_destroytable(atom_table *" t ); |
| 41 | |
| 42 | .BI "atom *atom_intern(atom_table *" t ", const char *" p ); |
| 43 | .BI "atom *atom_nintern(atom_table *" t ", const char *" p ", size_t " n ); |
| 44 | .BI "atom *atom_gensym(atom_table *" t ); |
| 45 | .BI "atom *INTERN(const char *" p ); |
| 46 | .BI "atom *GENSYM;" |
| 47 | |
| 48 | .BI "const char *atom_name(const atom *" a ); |
| 49 | .BI "size_t atom_len(const atom *" a ); |
| 50 | .BI "uint32 atom_hash(const atom *" a ); |
| 51 | .BI "const char *ATOM_NAME(const atom *" a ); |
| 52 | .BI "size_t ATOM_LEN(const atom *" a ); |
| 53 | .BI "uint32 ATOM_HASH(const atom *" a ); |
| 54 | |
| 55 | .BI "void atom_mkiter(atom_iter *" i ", atom_table *" t ); |
| 56 | .BI "atom *atom_next(atom_iter *" i ); |
| 57 | |
| 58 | .BI "extern atom_table *ATOM_GLOBAL;" |
| 59 | .fi |
| 60 | .SH DESCRIPTION |
| 61 | The |
| 62 | .B atom |
| 63 | functions and macros implement a data type similar to immutable strings, |
| 64 | with an additional property: that the addresses of two atoms from the |
| 65 | same table are equal if and only if they contain the same text. Atom |
| 66 | strings don't have to be null-terminated, although the interface is |
| 67 | simpler if you know that all of your atoms are null-terminated. It's |
| 68 | also possible to make |
| 69 | .IR "uninterned atoms" : |
| 70 | see below. |
| 71 | .PP |
| 72 | If a necessary memory allocation fails during an atom operation, the |
| 73 | exception |
| 74 | .B EXC_NOMEM |
| 75 | is raised. |
| 76 | .PP |
| 77 | Atoms are useful for speeding up string comparisons, and for saving |
| 78 | memory when many possibly-identical strings need storing. |
| 79 | .PP |
| 80 | There is a global atom table, named |
| 81 | .BR ATOM_GLOBAL , |
| 82 | available for general use. You can initialize your own atom table if |
| 83 | either you want to ensure that the atoms are not shared with some other |
| 84 | table, or if you want to be able to free the atoms later. Private atom |
| 85 | tables have the type |
| 86 | .BR atom_table ; |
| 87 | initialize it using the function |
| 88 | .B atom_createtable |
| 89 | and free it when you're finished using |
| 90 | .BR atom_destroytable . |
| 91 | .SS "Creating atoms from strings" |
| 92 | The process of making atoms from strings is called |
| 93 | .IR interning . |
| 94 | The function |
| 95 | .B atom_nintern |
| 96 | takes an atom table, a string, and a length, and returns an atom with |
| 97 | the same text. If your string is null-terminated, you can instead use |
| 98 | .B atom_intern |
| 99 | which has no length argument; if, in addition, you want to use the |
| 100 | global atom table, you can use the single-argument |
| 101 | .B INTERN |
| 102 | macro, which takes just a null-terminated string. |
| 103 | .PP |
| 104 | A terminating null byte is always appended to an atom name. This is not |
| 105 | considered to be a part of the name itself, and does not contribute to |
| 106 | the atom's length as reported by the |
| 107 | .B ATOM_LEN |
| 108 | macro. |
| 109 | .SS "Uninterned atoms" |
| 110 | You can make an atom which is guaranteed to be distinct from every other |
| 111 | atom, and has no sensible text string, by calling |
| 112 | .BR atom_gensym , |
| 113 | passing it the address of your atom table. The macro |
| 114 | .B GENSYM |
| 115 | (which doesn't look like a function, and has no parentheses following |
| 116 | it!) will return a unique atom from the global table. Uninterned atoms |
| 117 | have a generated name of the form |
| 118 | .RB ` *gen- \fInnn * ' |
| 119 | where |
| 120 | .I nnn |
| 121 | is an atom-table-specific sequence number. This text is there as a |
| 122 | debugging convenience, and doesn't mean that the uninterned atom has the |
| 123 | same address as an interned atom with the same text. |
| 124 | .SS "Other enquiries about atoms" |
| 125 | Atoms can be interrogated to find their names and hashes. The macro |
| 126 | .B ATOM_NAME |
| 127 | returns a pointer to the atom's name (its text); |
| 128 | .B ATOM_LEN |
| 129 | returns the length of the atom's name, excluding the terminating null; |
| 130 | and |
| 131 | .B ATOM_HASH |
| 132 | returns the atom's hash value, which is useful if you want to use the |
| 133 | atom as a key in some other structure. There are lower-case function |
| 134 | versions of these, which have the same effect. There is little point in |
| 135 | using the functions. |
| 136 | .SS "Enumerating atoms" |
| 137 | You can iterate over the atoms in an atom table. The |
| 138 | .B atom_mkiter |
| 139 | function initializes an iterator object to iterate over a particular |
| 140 | atom table; |
| 141 | .B atom_next |
| 142 | returns the next atom from the iterator. Atoms are not returned in any |
| 143 | particular order. |
| 144 | .SH SEE ALSO |
| 145 | .BR assoc (3), |
| 146 | .BR hash (3), |
| 147 | .BR mLib (3). |
| 148 | .SH AUTHOR |
| 149 | Mark Wooding, <mdw@nsict.org> |