=head1	NAME

dkstr - String handling module

=head1	SYNOPSIS

  #include <dkstr.h>

  int    dkstr_casecmp(char *a, char *b);
  int    dkstr_ncmp(char *s1, char *s2, size_t n);
  char * dkstr_dup(char *a);
  char * dkstr_chr(char *str, int c);
  char * dkstr_rchr(char *str, int c);
  char * dkstr_start(char *str, char *whsp);
  void   dkstr_chomp(char *str, char *whsp);
  char * dkstr_next(char *str, char *whsp);
  int    dkstr_is_on(char *str);
  int    dkstr_is_bool(char *str);
  int    dkstr_array_index(char **array, char *str, int cs);
  int    dkstr_find_multi_part_cmd(char **c, char ***s, int cs);
  void   dkstr_delcomm(char *str, char commentstarter);
  size_t dkstr_explode(char **a, size_t sz, char *s, char *wh);
  int    dkstr_is_abbr(char *s, char *p, char c, int cs);
  int    dkstr_array_abbr(char **array,char *str,char sp,int cs);
  int    dkstr_find_multi_part_abbr(char **c, char ***s, char sc, int cs);
  int    dkstr_is_identifier(char *str);
  char  *dkstr_unquote(char *str, char *quotes);

=head1	DESCRIPTION

The dkstr module provides functions for string handling.

Some of the functions are fallbacks for functions which exist
on some - but not on all - *x systems.

=over	2

=item	* int    dkstr_casecmp(char *a, char *b);

compares two strings I<a> and <b> and returns 1 if a > b,
0 if both strings are equal and -1 if a < b (lexicographically).
Comparison is case-insenstive.
If available the function engages strcasecmp() or stricmp(). If these
functions are unavailable, the function provides fallback code.

=item	* int	dkstr_ncmp(char *s1, char *s2, size_t n);

compares two strings but uses maximally n bytes.
If available the function uses strncmp(). If this function is not available
the dkstr_ncmp() function provides fallback code.


=item	* char * dkstr_dup(char *a);

creates a copy of string I<a> in dynamically allocated memory and returns
a pointer to the copy.

To release memory used for the copy, call dkmem_free() or dk_delete().

=item	* char * dkstr_chr(char *str, int c);

searches for the first (left) occurance of character I<c> in string
I<str> and returns a pointer to it (or NULL).

=item	* char * dkstr_rchr(char *str, int c);

searches for the last (right) occurance of character I<c> in string
I<str> and returns a pointer to it (or NULL).

=item	* char * dkstr_start(char *str, char *whsp);

returns a pointer to the first text character (non-white-space) in
string I<str> (or NULL). The I<whsp> parameter is a string containing
all the characters which are white spaces. A NULL pointer here means
"use a standard set of white space characters".

=item	* void   dkstr_chomp(char *str, char *whsp);

removes trailing white spaces from string I<str>. The I<whsp>
parameter is a string consisting of all white space characters.

=item	* char * dkstr_next(char *str, char *whsp);

returns a pointer to the beginning of the "next" word in string
I<str>. The I<str> parameter must be a pointer to text, i.e. obtained
from dkstr_start(). The dkstr_next() function finishes the first
text word (sequence of non-white-spaces) by a zero-byte and returns a pointer
to the beginning of the next text word (or NULL).

=item	* int    dkstr_is_on(char *str);

checks whether or not the I<str> string is one of the following:
"1", "yes", "on", "ok", "true" or an abbrebiation.

=item	* int    dkstr_is_bool(char *str);

checks whether or not the I<str> string is one of the following:
"0", "no", "off", "false",
"1", "yes", "on", "ok", "true" or an abbrebiation.

=item	* int    dkstr_array_index(char **array, char *str, int cs);

searches in an I<array> of strings whether the string I<str> is contained
and returns the index of I<str> in the I<array> or -1 if the string
is not contained in the I<array>. The I<array> must be finished by
a NULL pointer. The I<cs> parameter - if set to non-zero - requests
case-sensitive search, otherwise search is case-insensitive.

=item	* void   dkstr_delcomm(char *str, char commentstarter);

removes trailing comments from a line I<str>. The I<commentstarter>
parameter specifies the character which starts a comment spanning until
the end of line.

=item	* size_t dkstr_explode(char **a, size_t sz, char *s, char *wh);

divides a text I<s> line into text words (sequences of non-white-spaces).
The I<wh> string consists of characters which are white spaces.
The result is stored into array I<a> which is an array of pointers to
strings. The I<sz> parameter is the number of pointers available in the
array.

The function returns the number of pointers used (the number of
text words found in the string).

=item	* int    dkstr_find_multi_part_cmd(char **c, char ***s, int cs);

searches for multi-part string I<c> (array of strings) in an array
of multi-part commands I<s> and returns the index or -1.
The I<cs> parameter requires case-sensitive search if set.

Example:

Imagine a program that can read configuration files containing

  allow ip adresses = ...
  allow user name = ...
  allow user group = ...

When running, this program splits each configuration file line at
the "=" sign and splits the left side into substrings.
To handle the right side the program needs to identify the left side.

=item	* int    dkstr_is_abbr(char *s, char *p, char c, int cs);

checks whether the string I<s> matches the string I<p> or is an
abbreviation of I<p>. The I<c> parameter specifies the abbreviation
marker, I<c> requires a case-sensitive search.

  dkstr_is_abbr(s, "bo$ld", '$', 0)

will succeed, if I<s> is "bold", "bol" or "bo" but not "b", "black"
or "white".

The abbreviation marker is at the end of that text which is absolutely
necessary.

=item	* int    dkstr_array_abbr(char **array,char *str,char sp,int cs);

searches in an I<array> of patterns for the string I<str> and returns
the index or -1. The I<sp> parameter specifies the character indicating
the abbreviation position, I<cs> requires case-sensitive search if set.

Example

  char *test_patterns = {
    "us$er",
    "ho$stname",
    "mac$-address",
    NULL
  };
  ...
  i = dkstr_array_abbr(test_patterns, s, '$', 1);
  switch(i) {
    ...
  }

=item	* int    dkstr_find_multi_part_abbr(char **c, char ***s, char sc, int cs);
searches for a multi-part command I<c> in a multi-part pattern array I<s> and
returns the index or -1. The I<sc> parameter is the character marking the
abbreviation position, I<cs> requires case-sensitive search.

Example:

Image a program allow configuration file entries like

  allow hosts = ...
  allow user name = ...

The source code may contain

  char *cmd1[] = { "al$low", "h$osts", NULL };
  char *cmd2[] = { "al$low", "u$ser", "n$ame", NULL };
  char **commands[] = {
    cmd1, cmd2,
    NULL
  }
  
  i = dkstr_find_multi_part_abbr(c, commands, '$', 1);
  switch(i) {
    ...
  }

Now we can write a configuration file like

  al h = 192.168.101.1 192.168.101.2
  al u n = jim joe jack

=item	* int    dkstr_is_identifier(char *str);

checks whether or not the string I<str> is an identifier
(begins with character or underscore, continued by an optional sequence
of characters, underscores and digits.

=item	char  *dkstr_unquote(char *str, char *quotes);

returns a pointer to a string withtout quotes if the string is quoted.
Otherwise the original I<str> pointer is returned.

=back

=head1	RETURN VALUE

Unless stated otherwise functions returning int return a non-zero value
to indicate "yes", "flag is set". Zero is returned to indicate "no"
or "flag ist not set".

Functions returning pointers return a valid pointer on success. A
NULL pointer is returned to indicate that no matching character or
substring was found.

=head1	AUTHOR

Dirk Krause

=head1	COPYRIGHT AND LICENSE

Copyright (c) 2001-2008, Dirk Krause
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above
   copyright notice, this list of conditions and the
   following disclaimer.

 * Redistributions in binary form must reproduce the above
   copyright notice, this list of conditions and the following
   disclaimer in the documentation and/or other materials
   provided with the distribution.

 * Neither the name of the Dirk Krause nor the names of
   contributors may be used to endorse or promote products
   derived from this software without specific prior written
   permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
