Blame manual/search.texi

Packit 6c4009
@node Searching and Sorting, Pattern Matching, Message Translation, Top
Packit 6c4009
@c %MENU% General searching and sorting functions
Packit 6c4009
@chapter Searching and Sorting
Packit 6c4009
Packit 6c4009
This chapter describes functions for searching and sorting arrays of
Packit 6c4009
arbitrary objects.  You pass the appropriate comparison function to be
Packit 6c4009
applied as an argument, along with the size of the objects in the array
Packit 6c4009
and the total number of elements.
Packit 6c4009
Packit 6c4009
@menu
Packit 6c4009
* Comparison Functions::        Defining how to compare two objects.
Packit 6c4009
				 Since the sort and search facilities
Packit 6c4009
                                 are general, you have to specify the
Packit 6c4009
                                 ordering.
Packit 6c4009
* Array Search Function::       The @code{bsearch} function.
Packit 6c4009
* Array Sort Function::         The @code{qsort} function.
Packit 6c4009
* Search/Sort Example::         An example program.
Packit 6c4009
* Hash Search Function::        The @code{hsearch} function.
Packit 6c4009
* Tree Search Function::        The @code{tsearch} function.
Packit 6c4009
@end menu
Packit 6c4009
Packit 6c4009
@node Comparison Functions
Packit 6c4009
@section Defining the Comparison Function
Packit 6c4009
@cindex Comparison Function
Packit 6c4009
Packit 6c4009
In order to use the sorted array library functions, you have to describe
Packit 6c4009
how to compare the elements of the array.
Packit 6c4009
Packit 6c4009
To do this, you supply a comparison function to compare two elements of
Packit 6c4009
the array.  The library will call this function, passing as arguments
Packit 6c4009
pointers to two array elements to be compared.  Your comparison function
Packit 6c4009
should return a value the way @code{strcmp} (@pxref{String/Array
Packit 6c4009
Comparison}) does: negative if the first argument is ``less'' than the
Packit 6c4009
second, zero if they are ``equal'', and positive if the first argument
Packit 6c4009
is ``greater''.
Packit 6c4009
Packit 6c4009
Here is an example of a comparison function which works with an array of
Packit 6c4009
numbers of type @code{double}:
Packit 6c4009
Packit 6c4009
@smallexample
Packit 6c4009
int
Packit 6c4009
compare_doubles (const void *a, const void *b)
Packit 6c4009
@{
Packit 6c4009
  const double *da = (const double *) a;
Packit 6c4009
  const double *db = (const double *) b;
Packit 6c4009
Packit 6c4009
  return (*da > *db) - (*da < *db);
Packit 6c4009
@}
Packit 6c4009
@end smallexample
Packit 6c4009
Packit 6c4009
The header file @file{stdlib.h} defines a name for the data type of
Packit 6c4009
comparison functions.  This type is a GNU extension.
Packit 6c4009
Packit 6c4009
@comment stdlib.h
Packit 6c4009
@comment GNU
Packit 6c4009
@tindex comparison_fn_t
Packit 6c4009
@smallexample
Packit 6c4009
int comparison_fn_t (const void *, const void *);
Packit 6c4009
@end smallexample
Packit 6c4009
Packit 6c4009
@node Array Search Function
Packit 6c4009
@section Array Search Function
Packit 6c4009
@cindex search function (for arrays)
Packit 6c4009
@cindex binary search function (for arrays)
Packit 6c4009
@cindex array search function
Packit 6c4009
Packit 6c4009
Generally searching for a specific element in an array means that
Packit 6c4009
potentially all elements must be checked.  @Theglibc{} contains
Packit 6c4009
functions to perform linear search.  The prototypes for the following
Packit 6c4009
two functions can be found in @file{search.h}.
Packit 6c4009
Packit 6c4009
@deftypefun {void *} lfind (const void *@var{key}, const void *@var{base}, size_t *@var{nmemb}, size_t @var{size}, comparison_fn_t @var{compar})
Packit 6c4009
@standards{SVID, search.h}
Packit 6c4009
@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
Packit 6c4009
The @code{lfind} function searches in the array with @code{*@var{nmemb}}
Packit 6c4009
elements of @var{size} bytes pointed to by @var{base} for an element
Packit 6c4009
which matches the one pointed to by @var{key}.  The function pointed to
Packit 6c4009
by @var{compar} is used to decide whether two elements match.
Packit 6c4009
Packit 6c4009
The return value is a pointer to the matching element in the array
Packit 6c4009
starting at @var{base} if it is found.  If no matching element is
Packit 6c4009
available @code{NULL} is returned.
Packit 6c4009
Packit 6c4009
The mean runtime of this function is @code{*@var{nmemb}}/2.  This
Packit 6c4009
function should only be used if elements often get added to or deleted from
Packit 6c4009
the array in which case it might not be useful to sort the array before
Packit 6c4009
searching.
Packit 6c4009
@end deftypefun
Packit 6c4009
Packit 6c4009
@deftypefun {void *} lsearch (const void *@var{key}, void *@var{base}, size_t *@var{nmemb}, size_t @var{size}, comparison_fn_t @var{compar})
Packit 6c4009
@standards{SVID, search.h}
Packit 6c4009
@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
Packit 6c4009
@c A signal handler that interrupted an insertion and performed an
Packit 6c4009
@c insertion itself would leave the array in a corrupt state (e.g. one
Packit 6c4009
@c new element initialized twice, with parts of both initializations
Packit 6c4009
@c prevailing, and another uninitialized element), but this is just a
Packit 6c4009
@c special case of races on user-controlled objects, that have to be
Packit 6c4009
@c avoided by users.
Packit 6c4009
Packit 6c4009
@c In case of cancellation, we know the array won't be left in a corrupt
Packit 6c4009
@c state; the new element is initialized before the element count is
Packit 6c4009
@c incremented, and the compiler can't reorder these operations because
Packit 6c4009
@c it can't know that they don't alias.  So, we'll either cancel after
Packit 6c4009
@c the increment and the initialization are both complete, or the
Packit 6c4009
@c increment won't have taken place, and so how far the initialization
Packit 6c4009
@c got doesn't matter.
Packit 6c4009
The @code{lsearch} function is similar to the @code{lfind} function.  It
Packit 6c4009
searches the given array for an element and returns it if found.  The
Packit 6c4009
difference is that if no matching element is found the @code{lsearch}
Packit 6c4009
function adds the object pointed to by @var{key} (with a size of
Packit 6c4009
@var{size} bytes) at the end of the array and it increments the value of
Packit 6c4009
@code{*@var{nmemb}} to reflect this addition.
Packit 6c4009
Packit 6c4009
This means for the caller that if it is not sure that the array contains
Packit 6c4009
the element one is searching for the memory allocated for the array
Packit 6c4009
starting at @var{base} must have room for at least @var{size} more
Packit 6c4009
bytes.  If one is sure the element is in the array it is better to use
Packit 6c4009
@code{lfind} so having more room in the array is always necessary when
Packit 6c4009
calling @code{lsearch}.
Packit 6c4009
@end deftypefun
Packit 6c4009
Packit 6c4009
To search a sorted array for an element matching the key, use the
Packit 6c4009
@code{bsearch} function.  The prototype for this function is in
Packit 6c4009
the header file @file{stdlib.h}.
Packit 6c4009
@pindex stdlib.h
Packit 6c4009
Packit 6c4009
@deftypefun {void *} bsearch (const void *@var{key}, const void *@var{array}, size_t @var{count}, size_t @var{size}, comparison_fn_t @var{compare})
Packit 6c4009
@standards{ISO, stdlib.h}
Packit 6c4009
@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
Packit 6c4009
The @code{bsearch} function searches the sorted array @var{array} for an object
Packit 6c4009
that is equivalent to @var{key}.  The array contains @var{count} elements,
Packit 6c4009
each of which is of size @var{size} bytes.
Packit 6c4009
Packit 6c4009
The @var{compare} function is used to perform the comparison.  This
Packit 6c4009
function is called with two pointer arguments and should return an
Packit 6c4009
integer less than, equal to, or greater than zero corresponding to
Packit 6c4009
whether its first argument is considered less than, equal to, or greater
Packit 6c4009
than its second argument.  The elements of the @var{array} must already
Packit 6c4009
be sorted in ascending order according to this comparison function.
Packit 6c4009
Packit 6c4009
The return value is a pointer to the matching array element, or a null
Packit 6c4009
pointer if no match is found.  If the array contains more than one element
Packit 6c4009
that matches, the one that is returned is unspecified.
Packit 6c4009
Packit 6c4009
This function derives its name from the fact that it is implemented
Packit 6c4009
using the binary search algorithm.
Packit 6c4009
@end deftypefun
Packit 6c4009
Packit 6c4009
@node Array Sort Function
Packit 6c4009
@section Array Sort Function
Packit 6c4009
@cindex sort function (for arrays)
Packit 6c4009
@cindex quick sort function (for arrays)
Packit 6c4009
@cindex array sort function
Packit 6c4009
Packit 6c4009
To sort an array using an arbitrary comparison function, use the
Packit 6c4009
@code{qsort} function.  The prototype for this function is in
Packit 6c4009
@file{stdlib.h}.
Packit 6c4009
@pindex stdlib.h
Packit 6c4009
Packit 6c4009
@deftypefun void qsort (void *@var{array}, size_t @var{count}, size_t @var{size}, comparison_fn_t @var{compare})
Packit 6c4009
@standards{ISO, stdlib.h}
Packit 6c4009
@safety{@prelim{}@mtsafe{}@assafe{}@acunsafe{@acucorrupt{}}}
Packit 6c4009
The @code{qsort} function sorts the array @var{array}.  The array
Packit 6c4009
contains @var{count} elements, each of which is of size @var{size}.
Packit 6c4009
Packit 6c4009
The @var{compare} function is used to perform the comparison on the
Packit 6c4009
array elements.  This function is called with two pointer arguments and
Packit 6c4009
should return an integer less than, equal to, or greater than zero
Packit 6c4009
corresponding to whether its first argument is considered less than,
Packit 6c4009
equal to, or greater than its second argument.
Packit 6c4009
Packit 6c4009
@cindex stable sorting
Packit 6c4009
@strong{Warning:} If two objects compare as equal, their order after
Packit 6c4009
sorting is unpredictable.  That is to say, the sorting is not stable.
Packit 6c4009
This can make a difference when the comparison considers only part of
Packit 6c4009
the elements.  Two elements with the same sort key may differ in other
Packit 6c4009
respects.
Packit 6c4009
Packit 6c4009
Although the object addresses passed to the comparison function lie
Packit 6c4009
within the array, they need not correspond with the original locations
Packit 6c4009
of those objects because the sorting algorithm may swap around objects
Packit 6c4009
in the array before making some comparisons.  The only way to perform
Packit 6c4009
a stable sort with @code{qsort} is to first augment the objects with a
Packit 6c4009
monotonic counter of some kind.
Packit 6c4009
Packit 6c4009
Here is a simple example of sorting an array of doubles in numerical
Packit 6c4009
order, using the comparison function defined above (@pxref{Comparison
Packit 6c4009
Functions}):
Packit 6c4009
Packit 6c4009
@smallexample
Packit 6c4009
@{
Packit 6c4009
  double *array;
Packit 6c4009
  int size;
Packit 6c4009
  @dots{}
Packit 6c4009
  qsort (array, size, sizeof (double), compare_doubles);
Packit 6c4009
@}
Packit 6c4009
@end smallexample
Packit 6c4009
Packit 6c4009
The @code{qsort} function derives its name from the fact that it was
Packit 6c4009
originally implemented using the ``quick sort'' algorithm.
Packit 6c4009
Packit 6c4009
The implementation of @code{qsort} in this library might not be an
Packit 6c4009
in-place sort and might thereby use an extra amount of memory to store
Packit 6c4009
the array.
Packit 6c4009
@end deftypefun
Packit 6c4009
Packit 6c4009
@node Search/Sort Example
Packit 6c4009
@section Searching and Sorting Example
Packit 6c4009
Packit 6c4009
Here is an example showing the use of @code{qsort} and @code{bsearch}
Packit 6c4009
with an array of structures.  The objects in the array are sorted
Packit 6c4009
by comparing their @code{name} fields with the @code{strcmp} function.
Packit 6c4009
Then, we can look up individual objects based on their names.
Packit 6c4009
Packit 6c4009
@comment This example is dedicated to the memory of Jim Henson.  RIP.
Packit 6c4009
@smallexample
Packit 6c4009
@include search.c.texi
Packit 6c4009
@end smallexample
Packit 6c4009
Packit 6c4009
@cindex Kermit the frog
Packit 6c4009
The output from this program looks like:
Packit 6c4009
Packit 6c4009
@smallexample
Packit 6c4009
Kermit, the frog
Packit 6c4009
Piggy, the pig
Packit 6c4009
Gonzo, the whatever
Packit 6c4009
Fozzie, the bear
Packit 6c4009
Sam, the eagle
Packit 6c4009
Robin, the frog
Packit 6c4009
Animal, the animal
Packit 6c4009
Camilla, the chicken
Packit 6c4009
Sweetums, the monster
Packit 6c4009
Dr. Strangepork, the pig
Packit 6c4009
Link Hogthrob, the pig
Packit 6c4009
Zoot, the human
Packit 6c4009
Dr. Bunsen Honeydew, the human
Packit 6c4009
Beaker, the human
Packit 6c4009
Swedish Chef, the human
Packit 6c4009
Packit 6c4009
Animal, the animal
Packit 6c4009
Beaker, the human
Packit 6c4009
Camilla, the chicken
Packit 6c4009
Dr. Bunsen Honeydew, the human
Packit 6c4009
Dr. Strangepork, the pig
Packit 6c4009
Fozzie, the bear
Packit 6c4009
Gonzo, the whatever
Packit 6c4009
Kermit, the frog
Packit 6c4009
Link Hogthrob, the pig
Packit 6c4009
Piggy, the pig
Packit 6c4009
Robin, the frog
Packit 6c4009
Sam, the eagle
Packit 6c4009
Swedish Chef, the human
Packit 6c4009
Sweetums, the monster
Packit 6c4009
Zoot, the human
Packit 6c4009
Packit 6c4009
Kermit, the frog
Packit 6c4009
Gonzo, the whatever
Packit 6c4009
Couldn't find Janice.
Packit 6c4009
@end smallexample
Packit 6c4009
Packit 6c4009
Packit 6c4009
@node Hash Search Function
Packit 6c4009
@section The @code{hsearch} function.
Packit 6c4009
Packit 6c4009
The functions mentioned so far in this chapter are for searching in a sorted
Packit 6c4009
or unsorted array.  There are other methods to organize information
Packit 6c4009
which later should be searched.  The costs of insert, delete and search
Packit 6c4009
differ.  One possible implementation is using hashing tables.
Packit 6c4009
The following functions are declared in the header file @file{search.h}.
Packit 6c4009
Packit 6c4009
@deftypefun int hcreate (size_t @var{nel})
Packit 6c4009
@standards{SVID, search.h}
Packit 6c4009
@safety{@prelim{}@mtunsafe{@mtasurace{:hsearch}}@asunsafe{@ascuheap{}}@acunsafe{@acucorrupt{} @acsmem{}}}
Packit 6c4009
@c hcreate @mtasurace:hsearch @ascuheap @acucorrupt @acsmem
Packit 6c4009
@c  hcreate_r dup @mtsrace:htab @ascuheap @acucorrupt @acsmem
Packit 6c4009
The @code{hcreate} function creates a hashing table which can contain at
Packit 6c4009
least @var{nel} elements.  There is no possibility to grow this table so
Packit 6c4009
it is necessary to choose the value for @var{nel} wisely.  The method
Packit 6c4009
used to implement this function might make it necessary to make the
Packit 6c4009
number of elements in the hashing table larger than the expected maximal
Packit 6c4009
number of elements.  Hashing tables usually work inefficiently if they are
Packit 6c4009
filled 80% or more.  The constant access time guaranteed by hashing can
Packit 6c4009
only be achieved if few collisions exist.  See Knuth's ``The Art of
Packit 6c4009
Computer Programming, Part 3: Searching and Sorting'' for more
Packit 6c4009
information.
Packit 6c4009
Packit 6c4009
The weakest aspect of this function is that there can be at most one
Packit 6c4009
hashing table used through the whole program.  The table is allocated
Packit 6c4009
in local memory out of control of the programmer.  As an extension @theglibc{}
Packit 6c4009
provides an additional set of functions with a reentrant
Packit 6c4009
interface which provides a similar interface but which allows keeping
Packit 6c4009
arbitrarily many hashing tables.
Packit 6c4009
Packit 6c4009
It is possible to use more than one hashing table in the program run if
Packit 6c4009
the former table is first destroyed by a call to @code{hdestroy}.
Packit 6c4009
Packit 6c4009
The function returns a non-zero value if successful.  If it returns zero,
Packit 6c4009
something went wrong.  This could either mean there is already a hashing
Packit 6c4009
table in use or the program ran out of memory.
Packit 6c4009
@end deftypefun
Packit 6c4009
Packit 6c4009
@deftypefun void hdestroy (void)
Packit 6c4009
@standards{SVID, search.h}
Packit 6c4009
@safety{@prelim{}@mtunsafe{@mtasurace{:hsearch}}@asunsafe{@ascuheap{}}@acunsafe{@acucorrupt{} @acsmem{}}}
Packit 6c4009
@c hdestroy @mtasurace:hsearch @ascuheap @acucorrupt @acsmem
Packit 6c4009
@c  hdestroy_r dup @mtsrace:htab @ascuheap @acucorrupt @acsmem
Packit 6c4009
The @code{hdestroy} function can be used to free all the resources
Packit 6c4009
allocated in a previous call of @code{hcreate}.  After a call to this
Packit 6c4009
function it is again possible to call @code{hcreate} and allocate a new
Packit 6c4009
table with possibly different size.
Packit 6c4009
Packit 6c4009
It is important to remember that the elements contained in the hashing
Packit 6c4009
table at the time @code{hdestroy} is called are @emph{not} freed by this
Packit 6c4009
function.  It is the responsibility of the program code to free those
Packit 6c4009
strings (if necessary at all).  Freeing all the element memory is not
Packit 6c4009
possible without extra, separately kept information since there is no
Packit 6c4009
function to iterate through all available elements in the hashing table.
Packit 6c4009
If it is really necessary to free a table and all elements the
Packit 6c4009
programmer has to keep a list of all table elements and before calling
Packit 6c4009
@code{hdestroy} s/he has to free all element's data using this list.
Packit 6c4009
This is a very unpleasant mechanism and it also shows that this kind of
Packit 6c4009
hashing table is mainly meant for tables which are created once and
Packit 6c4009
used until the end of the program run.
Packit 6c4009
@end deftypefun
Packit 6c4009
Packit 6c4009
Entries of the hashing table and keys for the search are defined using
Packit 6c4009
this type:
Packit 6c4009
Packit 6c4009
@deftp {Data type} {struct ENTRY}
Packit 6c4009
Both elements of this structure are pointers to zero-terminated strings.
Packit 6c4009
This is a limiting restriction of the functionality of the
Packit 6c4009
@code{hsearch} functions.  They can only be used for data sets which use
Packit 6c4009
the NUL character always and solely to terminate the records.  It is not
Packit 6c4009
possible to handle general binary data.
Packit 6c4009
Packit 6c4009
@table @code
Packit 6c4009
@item char *key
Packit 6c4009
Pointer to a zero-terminated string of characters describing the key for
Packit 6c4009
the search or the element in the hashing table.
Packit 6c4009
@item char *data
Packit 6c4009
Pointer to a zero-terminated string of characters describing the data.
Packit 6c4009
If the functions will be called only for searching an existing entry
Packit 6c4009
this element might stay undefined since it is not used.
Packit 6c4009
@end table
Packit 6c4009
@end deftp
Packit 6c4009
Packit 6c4009
@deftypefun {ENTRY *} hsearch (ENTRY @var{item}, ACTION @var{action})
Packit 6c4009
@standards{SVID, search.h}
Packit 6c4009
@safety{@prelim{}@mtunsafe{@mtasurace{:hsearch}}@asunsafe{}@acunsafe{@acucorrupt{/action==ENTER}}}
Packit 6c4009
@c hsearch @mtasurace:hsearch @acucorrupt/action==ENTER
Packit 6c4009
@c  hsearch_r dup @mtsrace:htab @acucorrupt/action==ENTER
Packit 6c4009
To search in a hashing table created using @code{hcreate} the
Packit 6c4009
@code{hsearch} function must be used.  This function can perform a simple
Packit 6c4009
search for an element (if @var{action} has the value @code{FIND}) or it can
Packit 6c4009
alternatively insert the key element into the hashing table.  Entries
Packit 6c4009
are never replaced.
Packit 6c4009
Packit 6c4009
The key is denoted by a pointer to an object of type @code{ENTRY}.  For
Packit 6c4009
locating the corresponding position in the hashing table only the
Packit 6c4009
@code{key} element of the structure is used.
Packit 6c4009
Packit 6c4009
If an entry with a matching key is found the @var{action} parameter is
Packit 6c4009
irrelevant.  The found entry is returned.  If no matching entry is found
Packit 6c4009
and the @var{action} parameter has the value @code{FIND} the function
Packit 6c4009
returns a @code{NULL} pointer.  If no entry is found and the
Packit 6c4009
@var{action} parameter has the value @code{ENTER} a new entry is added
Packit 6c4009
to the hashing table which is initialized with the parameter @var{item}.
Packit 6c4009
A pointer to the newly added entry is returned.
Packit 6c4009
@end deftypefun
Packit 6c4009
Packit 6c4009
As mentioned before, the hashing table used by the functions described so
Packit 6c4009
far is global and there can be at any time at most one hashing table in
Packit 6c4009
the program.  A solution is to use the following functions which are a
Packit 6c4009
GNU extension.  All have in common that they operate on a hashing table
Packit 6c4009
which is described by the content of an object of the type @code{struct
Packit 6c4009
hsearch_data}.  This type should be treated as opaque, none of its
Packit 6c4009
members should be changed directly.
Packit 6c4009
Packit 6c4009
@deftypefun int hcreate_r (size_t @var{nel}, struct hsearch_data *@var{htab})
Packit 6c4009
@standards{GNU, search.h}
Packit 6c4009
@safety{@prelim{}@mtsafe{@mtsrace{:htab}}@asunsafe{@ascuheap{}}@acunsafe{@acucorrupt{} @acsmem{}}}
Packit 6c4009
@c Unlike the lsearch array, the htab is (at least in part) opaque, so
Packit 6c4009
@c let's make it absolutely clear that ensuring exclusive access is a
Packit 6c4009
@c caller responsibility.
Packit 6c4009
Packit 6c4009
@c Cancellation is unlikely to leave the htab in a corrupt state: the
Packit 6c4009
@c last field to be initialized is the one that tells whether the entire
Packit 6c4009
@c data structure was initialized, and there's a function call (calloc)
Packit 6c4009
@c in between that will often ensure all other fields are written before
Packit 6c4009
@c the table.  However, should this call be inlined (say with LTO), this
Packit 6c4009
@c assumption may not hold.  The calloc call doesn't cross our library
Packit 6c4009
@c interface barrier, so let's consider this could happen and mark this
Packit 6c4009
@c with @acucorrupt.  It's no safety loss, since we already have
Packit 6c4009
@c @ascuheap anyway...
Packit 6c4009
Packit 6c4009
@c hcreate_r @mtsrace:htab @ascuheap @acucorrupt @acsmem
Packit 6c4009
@c  isprime ok
Packit 6c4009
@c  calloc dup @ascuheap @acsmem
Packit 6c4009
The @code{hcreate_r} function initializes the object pointed to by
Packit 6c4009
@var{htab} to contain a hashing table with at least @var{nel} elements.
Packit 6c4009
So this function is equivalent to the @code{hcreate} function except
Packit 6c4009
that the initialized data structure is controlled by the user.
Packit 6c4009
Packit 6c4009
This allows having more than one hashing table at one time.  The memory
Packit 6c4009
necessary for the @code{struct hsearch_data} object can be allocated
Packit 6c4009
dynamically.  It must be initialized with zero before calling this
Packit 6c4009
function.
Packit 6c4009
Packit 6c4009
The return value is non-zero if the operation was successful.  If the
Packit 6c4009
return value is zero, something went wrong, which probably means the
Packit 6c4009
program ran out of memory.
Packit 6c4009
@end deftypefun
Packit 6c4009
Packit 6c4009
@deftypefun void hdestroy_r (struct hsearch_data *@var{htab})
Packit 6c4009
@standards{GNU, search.h}
Packit 6c4009
@safety{@prelim{}@mtsafe{@mtsrace{:htab}}@asunsafe{@ascuheap{}}@acunsafe{@acucorrupt{} @acsmem{}}}
Packit 6c4009
@c The table is released while the table pointer still points to it.
Packit 6c4009
@c Async cancellation is thus unsafe, but it already was because we call
Packit 6c4009
@c free().  Using the table in a handler while it's being released would
Packit 6c4009
@c also be dangerous, but calling free() already makes it unsafe, and
Packit 6c4009
@c the requirement on the caller to ensure exclusive access already
Packit 6c4009
@c guarantees this doesn't happen, so we don't get @asucorrupt.
Packit 6c4009
Packit 6c4009
@c hdestroy_r @mtsrace:htab @ascuheap @acucorrupt @acsmem
Packit 6c4009
@c  free dup @ascuheap @acsmem
Packit 6c4009
The @code{hdestroy_r} function frees all resources allocated by the
Packit 6c4009
@code{hcreate_r} function for this very same object @var{htab}.  As for
Packit 6c4009
@code{hdestroy} it is the program's responsibility to free the strings
Packit 6c4009
for the elements of the table.
Packit 6c4009
@end deftypefun
Packit 6c4009
Packit 6c4009
@deftypefun int hsearch_r (ENTRY @var{item}, ACTION @var{action}, ENTRY **@var{retval}, struct hsearch_data *@var{htab})
Packit 6c4009
@standards{GNU, search.h}
Packit 6c4009
@safety{@prelim{}@mtsafe{@mtsrace{:htab}}@assafe{}@acunsafe{@acucorrupt{/action==ENTER}}}
Packit 6c4009
@c Callers have to ensure mutual exclusion; insertion, if cancelled,
Packit 6c4009
@c leaves the table in a corrupt state.
Packit 6c4009
Packit 6c4009
@c hsearch_r @mtsrace:htab @acucorrupt/action==ENTER
Packit 6c4009
@c  strlen dup ok
Packit 6c4009
@c  strcmp dup ok
Packit 6c4009
The @code{hsearch_r} function is equivalent to @code{hsearch}.  The
Packit 6c4009
meaning of the first two arguments is identical.  But instead of
Packit 6c4009
operating on a single global hashing table the function works on the
Packit 6c4009
table described by the object pointed to by @var{htab} (which is
Packit 6c4009
initialized by a call to @code{hcreate_r}).
Packit 6c4009
Packit 6c4009
Another difference to @code{hcreate} is that the pointer to the found
Packit 6c4009
entry in the table is not the return value of the function.  It is
Packit 6c4009
returned by storing it in a pointer variable pointed to by the
Packit 6c4009
@var{retval} parameter.  The return value of the function is an integer
Packit 6c4009
value indicating success if it is non-zero and failure if it is zero.
Packit 6c4009
In the latter case the global variable @var{errno} signals the reason for
Packit 6c4009
the failure.
Packit 6c4009
Packit 6c4009
@table @code
Packit 6c4009
@item ENOMEM
Packit 6c4009
The table is filled and @code{hsearch_r} was called with a so far
Packit 6c4009
unknown key and @var{action} set to @code{ENTER}.
Packit 6c4009
@item ESRCH
Packit 6c4009
The @var{action} parameter is @code{FIND} and no corresponding element
Packit 6c4009
is found in the table.
Packit 6c4009
@end table
Packit 6c4009
@end deftypefun
Packit 6c4009
Packit 6c4009
Packit 6c4009
@node Tree Search Function
Packit 6c4009
@section The @code{tsearch} function.
Packit 6c4009
Packit 6c4009
Another common form to organize data for efficient search is to use
Packit 6c4009
trees.  The @code{tsearch} function family provides a nice interface to
Packit 6c4009
functions to organize possibly large amounts of data by providing a mean
Packit 6c4009
access time proportional to the logarithm of the number of elements.
Packit 6c4009
@Theglibc{} implementation even guarantees that this bound is
Packit 6c4009
never exceeded even for input data which cause problems for simple
Packit 6c4009
binary tree implementations.
Packit 6c4009
Packit 6c4009
The functions described in the chapter are all described in the @w{System
Packit 6c4009
V} and X/Open specifications and are therefore quite portable.
Packit 6c4009
Packit 6c4009
In contrast to the @code{hsearch} functions the @code{tsearch} functions
Packit 6c4009
can be used with arbitrary data and not only zero-terminated strings.
Packit 6c4009
Packit 6c4009
The @code{tsearch} functions have the advantage that no function to
Packit 6c4009
initialize data structures is necessary.  A simple pointer of type
Packit 6c4009
@code{void *} initialized to @code{NULL} is a valid tree and can be
Packit 6c4009
extended or searched.  The prototypes for these functions can be found
Packit 6c4009
in the header file @file{search.h}.
Packit 6c4009
Packit 6c4009
@deftypefun {void *} tsearch (const void *@var{key}, void **@var{rootp}, comparison_fn_t @var{compar})
Packit 6c4009
@standards{SVID, search.h}
Packit 6c4009
@safety{@prelim{}@mtsafe{@mtsrace{:rootp}}@asunsafe{@ascuheap{}}@acunsafe{@acucorrupt{} @acsmem{}}}
Packit 6c4009
@c The tree is not modified in a thread-safe manner, and rotations may
Packit 6c4009
@c leave the tree in an inconsistent state that could be observed in an
Packit 6c4009
@c asynchronous signal handler (except for the caller-synchronization
Packit 6c4009
@c requirement) or after asynchronous cancellation of the thread
Packit 6c4009
@c performing the rotation or the insertion.
Packit 6c4009
The @code{tsearch} function searches in the tree pointed to by
Packit 6c4009
@code{*@var{rootp}} for an element matching @var{key}.  The function
Packit 6c4009
pointed to by @var{compar} is used to determine whether two elements
Packit 6c4009
match.  @xref{Comparison Functions}, for a specification of the functions
Packit 6c4009
which can be used for the @var{compar} parameter.
Packit 6c4009
Packit 6c4009
If the tree does not contain a matching entry the @var{key} value will
Packit 6c4009
be added to the tree.  @code{tsearch} does not make a copy of the object
Packit 6c4009
pointed to by @var{key} (how could it since the size is unknown).
Packit 6c4009
Instead it adds a reference to this object which means the object must
Packit 6c4009
be available as long as the tree data structure is used.
Packit 6c4009
Packit 6c4009
The tree is represented by a pointer to a pointer since it is sometimes
Packit 6c4009
necessary to change the root node of the tree.  So it must not be
Packit 6c4009
assumed that the variable pointed to by @var{rootp} has the same value
Packit 6c4009
after the call.  This also shows that it is not safe to call the
Packit 6c4009
@code{tsearch} function more than once at the same time using the same
Packit 6c4009
tree.  It is no problem to run it more than once at a time on different
Packit 6c4009
trees.
Packit 6c4009
Packit 6c4009
The return value is a pointer to the matching element in the tree.  If a
Packit 6c4009
new element was created the pointer points to the new data (which is in
Packit 6c4009
fact @var{key}).  If an entry had to be created and the program ran out
Packit 6c4009
of space @code{NULL} is returned.
Packit 6c4009
@end deftypefun
Packit 6c4009
Packit 6c4009
@deftypefun {void *} tfind (const void *@var{key}, void *const *@var{rootp}, comparison_fn_t @var{compar})
Packit 6c4009
@standards{SVID, search.h}
Packit 6c4009
@safety{@prelim{}@mtsafe{@mtsrace{:rootp}}@assafe{}@acsafe{}}
Packit 6c4009
The @code{tfind} function is similar to the @code{tsearch} function.  It
Packit 6c4009
locates an element matching the one pointed to by @var{key} and returns
Packit 6c4009
a pointer to this element.  But if no matching element is available no
Packit 6c4009
new element is entered (note that the @var{rootp} parameter points to a
Packit 6c4009
constant pointer).  Instead the function returns @code{NULL}.
Packit 6c4009
@end deftypefun
Packit 6c4009
Packit 6c4009
Another advantage of the @code{tsearch} functions in contrast to the
Packit 6c4009
@code{hsearch} functions is that there is an easy way to remove
Packit 6c4009
elements.
Packit 6c4009
Packit 6c4009
@deftypefun {void *} tdelete (const void *@var{key}, void **@var{rootp}, comparison_fn_t @var{compar})
Packit 6c4009
@standards{SVID, search.h}
Packit 6c4009
@safety{@prelim{}@mtsafe{@mtsrace{:rootp}}@asunsafe{@ascuheap{}}@acunsafe{@acucorrupt{} @acsmem{}}}
Packit 6c4009
To remove a specific element matching @var{key} from the tree
Packit 6c4009
@code{tdelete} can be used.  It locates the matching element using the
Packit 6c4009
same method as @code{tfind}.  The corresponding element is then removed
Packit 6c4009
and a pointer to the parent of the deleted node is returned by the
Packit 6c4009
function.  If there is no matching entry in the tree nothing can be
Packit 6c4009
deleted and the function returns @code{NULL}.  If the root of the tree
Packit 6c4009
is deleted @code{tdelete} returns some unspecified value not equal to
Packit 6c4009
@code{NULL}.
Packit 6c4009
@end deftypefun
Packit 6c4009
Packit 6c4009
@deftypefun void tdestroy (void *@var{vroot}, __free_fn_t @var{freefct})
Packit 6c4009
@standards{GNU, search.h}
Packit 6c4009
@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}}
Packit 6c4009
If the complete search tree has to be removed one can use
Packit 6c4009
@code{tdestroy}.  It frees all resources allocated by the @code{tsearch}
Packit 6c4009
functions to generate the tree pointed to by @var{vroot}.
Packit 6c4009
Packit 6c4009
For the data in each tree node the function @var{freefct} is called.
Packit 6c4009
The pointer to the data is passed as the argument to the function.  If
Packit 6c4009
no such work is necessary @var{freefct} must point to a function doing
Packit 6c4009
nothing.  It is called in any case.
Packit 6c4009
Packit 6c4009
This function is a GNU extension and not covered by the @w{System V} or
Packit 6c4009
X/Open specifications.
Packit 6c4009
@end deftypefun
Packit 6c4009
Packit 6c4009
In addition to the functions to create and destroy the tree data
Packit 6c4009
structure, there is another function which allows you to apply a
Packit 6c4009
function to all elements of the tree.  The function must have this type:
Packit 6c4009
Packit 6c4009
@smallexample
Packit 6c4009
void __action_fn_t (const void *nodep, VISIT value, int level);
Packit 6c4009
@end smallexample
Packit 6c4009
Packit 6c4009
The @var{nodep} is the data value of the current node (once given as the
Packit 6c4009
@var{key} argument to @code{tsearch}).  @var{level} is a numeric value
Packit 6c4009
which corresponds to the depth of the current node in the tree.  The
Packit 6c4009
root node has the depth @math{0} and its children have a depth of
Packit 6c4009
@math{1} and so on.  The @code{VISIT} type is an enumeration type.
Packit 6c4009
Packit 6c4009
@deftp {Data Type} VISIT
Packit 6c4009
The @code{VISIT} value indicates the status of the current node in the
Packit 6c4009
tree and how the function is called.  The status of a node is either
Packit 6c4009
`leaf' or `internal node'.  For each leaf node the function is called
Packit 6c4009
exactly once, for each internal node it is called three times: before
Packit 6c4009
the first child is processed, after the first child is processed and
Packit 6c4009
after both children are processed.  This makes it possible to handle all
Packit 6c4009
three methods of tree traversal (or even a combination of them).
Packit 6c4009
Packit 6c4009
@vtable @code
Packit 6c4009
@item preorder
Packit 6c4009
The current node is an internal node and the function is called before
Packit 6c4009
the first child was processed.
Packit 6c4009
@item postorder
Packit 6c4009
The current node is an internal node and the function is called after
Packit 6c4009
the first child was processed.
Packit 6c4009
@item endorder
Packit 6c4009
The current node is an internal node and the function is called after
Packit 6c4009
the second child was processed.
Packit 6c4009
@item leaf
Packit 6c4009
The current node is a leaf.
Packit 6c4009
@end vtable
Packit 6c4009
@end deftp
Packit 6c4009
Packit 6c4009
@deftypefun void twalk (const void *@var{root}, __action_fn_t @var{action})
Packit 6c4009
@standards{SVID, search.h}
Packit 6c4009
@safety{@prelim{}@mtsafe{@mtsrace{:root}}@assafe{}@acsafe{}}
Packit 6c4009
For each node in the tree with a node pointed to by @var{root}, the
Packit 6c4009
@code{twalk} function calls the function provided by the parameter
Packit 6c4009
@var{action}.  For leaf nodes the function is called exactly once with
Packit 6c4009
@var{value} set to @code{leaf}.  For internal nodes the function is
Packit 6c4009
called three times, setting the @var{value} parameter or @var{action} to
Packit 6c4009
the appropriate value.  The @var{level} argument for the @var{action}
Packit 6c4009
function is computed while descending the tree by increasing the value
Packit 6c4009
by one for each descent to a child, starting with the value @math{0} for
Packit 6c4009
the root node.
Packit 6c4009
Packit 6c4009
Since the functions used for the @var{action} parameter to @code{twalk}
Packit 6c4009
must not modify the tree data, it is safe to run @code{twalk} in more
Packit 6c4009
than one thread at the same time, working on the same tree.  It is also
Packit 6c4009
safe to call @code{tfind} in parallel.  Functions which modify the tree
Packit 6c4009
must not be used, otherwise the behavior is undefined.
Packit 6c4009
@end deftypefun