/*
Copyright (c) 2000-2010, 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 
  opyright 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.
*/

/**	@file dkstr.h
String functions.
This module contains functions to handle strings.

Unless otherwise stated, int functions in this module return a positive
number to indicate success or a true condition, 0 to indicate an error
or an unfullfilled condition.
Pointer functions return valid pointers on success, NULL on error.
*/
#ifndef DK_STR_INCLUDED
#define DK_STR_INCLUDED 1

#include <dk.h>
#include <dktypes.h>

#if defined(EXTERN)
#undef EXTERN
#endif
#ifndef DK_STR_C
#if !DK_HAVE_PROTOTYPES
#define EXTERN extern
#else
#define EXTERN /* nix */
#endif
#else
#define EXTERN /* nix */
#endif

#if defined(__cplusplus)
extern "C" {
#endif

/**	Case insensitive comparison.
The function compares two strings \a a and \a b. The function returns 0 if both
strings are equal in a case-insensitive comparison, a positive value
if \a a > \a b or a negative value if \a a < \a b.
@param	a	One string.
@param	b	The other string.
@return	The comparison result.
*/
EXTERN int  dkstr_casecmp DK_PR((char *a, char *b));

/**	Duplicate a string.
The function allocates memory to create a copy of string \a a.
@param	a	The string to copy.
@return	A pointer to the new copy of the string.
Use dk_delete() to release the memory used by the copy if the copy
is not longer needed.
*/
EXTERN char * dkstr_dup DK_PR((char *a));

/**	Find first occurance of character.
The function searches for the first orrucance of \a c in string \a str
and returns a pointer to the address of \a c.
@param	c	The character to search for.
@param	str	The string to search for c.
@return
- Pointer to the first occurance of \a c found or
- NULL if \a str does not contain \a c.
*/
EXTERN char * dkstr_chr DK_PR((char *str, int c));

/**	Find last occurance of character.
The function searches for the last orrucance of \a c in string \a str
and returns a pointer to the address of \a c.
@param	c	The character to search for.
@param	str	The string to search for c.
@return
- Pointer to the last occurance of \a c found or
- NULL if \a str does not contain \a c.
*/
EXTERN char * dkstr_rchr DK_PR((char *str, int c));

/**	Delete comments from text line.
This function removes a comment started by the comment starter character
\a c from text line \a s by replacing the \a c character by a 0-byte.
The replacement is only done if \a c is not a part of a string in
single or double quotes.
@param	s	The string to modify.
@param	c	Special character marking the start of a comment.
*/
EXTERN void   dkstr_delcomm DK_PR((char *s, char c));

/**	Find start of text.
The function searches for the first non-whitespace in \a str and returns
a pointer to it.
@param	str	String to search for test.
@param	whsp	String containing all characters to treat as whitespaces.
This paramter can be NULL to use a default set of whitespaces.
@return	Pointer to the first text character (or NULL if there is no text).
*/
EXTERN char * dkstr_start DK_PR((char *str, char *whsp));

/**	Remove trailing whitespaces.
The function removes trailing whitespaces from a string.
@param	str	String to remove tailing whitespaces from.
@param	whsp	A string listing all whitespaces. This parameter can be set
to NULL to use a default set of whitespaces.
*/
EXTERN void  dkstr_chomp DK_PR((char *str, char *whsp));

/**	Find next text.
After finding the beginning of text in a string \a str this function
can be used to find the next text word in the string. The first text word
is finished using a 0-byte.
@param	str	The string to search for the next text word.
@param	whsp	A string listing all whitespaces. This paramter can be set
to NULL to use a default set of whitespaces.
@return	Pointer to the beginning of the second text word in \a str.
*/
EXTERN char * dkstr_next DK_PR((char *str, char *whsp));

/**	Check abbreviation.
The function checks whether or not the string \a s is an abbreviation
of pattern \a p. The special character \a c marks the beginning of the
optional part in pattern \a p. The \a cs parameter can be used to indicate
case-sensitive search.
@param	s	String to check.
@param	p	The pattern to compare against.
@param	c	Special character to mark the start of the optional part
of the pattern.
@param	cs	Flag for case-sensitive comparison.
@return	Positive value if the string matches the pattern, 0 if there
is no match.

If the special character c is '$' and the pattern \a p is 'h$elp' the
texts 'h', 'he', 'hel' and 'help' will match.
*/
EXTERN int    dkstr_is_abbr DK_PR((char *s, char *p, char c, int cs));

/**	Check whether text is a boolean value.
This function checks whether or not the text in \a str represents
a boolean value.
*/
EXTERN int    dkstr_is_bool DK_PR((char *str));

/**	Check whether text is the boolean value for true.
This function checks whether or not the text in \a str represents the
boolean value "true".
*/
EXTERN int    dkstr_is_on DK_PR((char *str));

/**	Find index of a text word in an array.
The function checks the string array \a a whether or not it contains
the string \a s and returns the index of \a s in \a a. The \a cs
parameter can be set to do a case-sensitive search.
@param	array	Array containing patterns.
@param	str	String to search for.
@param	cs	Flag to indicate case-sensitive search.
@return	The index of \a s in \a a (or -1 if the array does not contain the
string).
*/
EXTERN int    dkstr_array_index DK_PR((char **array, char *str, int cs));

/**	Find index of abbreviated text in an array.
The function checks the string array \a a whether or not \a s is an abbreviation
of one of the array elements. The character \a c introduces the optional
text in each array element. The \a cs parameter can be used to do a 
case-sensitive search.
@param	a	Array containing patterns.
@param	s	String to search for.
@param	c	Control character (introduces the optional part of the pattern).
@param	cs	Flag to indicate case-sensitive search.
@return	The index of the pattern matching \a s in \a a (or -1 if \a s was
not found).

If \a a contains a pattern 'h$elp' and c = '$' the strings 'h',
'he', 'hel' and 'help' will match the pattern.
*/
EXTERN int    dkstr_array_abbr DK_PR((char **a,char *s,char c,int cs));

/**	Explode multi-part string into array of strings.
The function splits the string \a s consisting of multiple text words into
a sequence of multiple strings containing one text word each.
The pointers to the beginnings of the text words are stored in array \a a.
@param	a	Array to store the pointers to the beginnings of the text words.
@param	sz	Number of array elements in \a a.
@param	s	The string to split.
@param	wh	A string listing all the whitespace characters.
@return	The number of array elements used in \a a.
*/
EXTERN size_t dkstr_explode DK_PR((char **a, size_t sz, char *s, char *wh));

/**	Find index of multi-word text in array of multi-word patterns.
The function searches for the index of a multi-word command \a c in an
array \a s of multi-word patterns and returns the index of the first
matching pattern.
@param	c	Multi-word command to search for (finished by a NULL pointer).
@param	s	Array of multi-word patterns (finished by a NULL pointer, each
pattern finished by a NULL pointer).
@param	cs	Flag to indicate case-sensitive search.
@return	The index of the matching pattern or -1 if no such pattern was found.
*/
EXTERN int    dkstr_find_multi_part_cmd DK_PR((char **c, char ***s, int cs));

/**	Find index of abbreviated multi-word text in array of multi-word
patterns.
The functions searches for the index of a multi-word command \a c in an
array \a s of multi-word patterns.
@param	c	The command to search for.
@param	s	The array of multi-word commands, allowing abbreviations.
@param	sc	Special character to mark the beginning of the optional
text word parts in the patterns.
@param	cs	Flag to indicate case-sensitive search.
@return	The index of the matching pattern or -1 if no such pattern was found.
*/
EXTERN int    dkstr_find_multi_part_abbr DK_PR((char **c, char ***s, char sc, int cs));

/**	Check whether a string is an identifier.
The function checks whether \a str is an languaidentifier in a programming
language (\a str must match [a-zA-Z_][a-zA-Z_01-9]+).
@param	str	String to check.
@return	1 if \a str is an identifier, 0 if not.
*/
EXTERN int    dkstr_is_identifier DK_PR((char *str));

/**	Unquote a string.
This function removes single or double quotes from a string and returns
a pointer to the result string.
@param	str	The source string.
@param	quotes	A string containing the characters representing quotes.
@return	A pointer to the string without surrounding quotes.
*/
EXTERN char  *dkstr_unquote DK_PR((char *str, char *quotes));



/**	Find occurance of character in string.
	@param	str	String.
	@param	c	Character to search for.
	@return	Pointer to position of first \a c in \a str on success,
		NULL on error.
*/
EXTERN wchar_t *
dkstr_w_chr DK_PR((wchar_t *str, wchar_t c));



/**	Find last occurance of character in string.
	@param	str	String.
	@param	c	Character to search for.
	@return	Pointer to position of rightmost \a c in \a str on success,
		NULL on error.
*/
EXTERN wchar_t *
dkstr_w_rchr DK_PR((wchar_t *str, wchar_t c));



/**	Find start of text in string.
	@param	str	String.
	@param	whsp	Set of whitespaces.
	@return	Pointer to first non-whitespace on success, NULL on error.
*/
EXTERN wchar_t *
dkstr_w_start DK_PR((wchar_t *str, wchar_t *whsp));



/**	Find second text in string.
	@param	str	String.
	@param	whsp	Set of whitespaces.
	@return	Pointer to second text in \a str on success, NULL on error.
*/
EXTERN wchar_t *
dkstr_w_next DK_PR((wchar_t *str, wchar_t *whsp));



/**	Remove leading and trailing spaces from string.
	@param	str	String to modify.
	@param	whsp	Set of whitespaces.
*/
EXTERN void
dkstr_w_chomp DK_PR((wchar_t *str, wchar_t *whsp));



/**	Case-insensitive string comparison.
	@param	a	Left string.
	@param	b	Right string.
	@return	Comparison result.
*/
EXTERN int
dkstr_w_casecmp DK_PR((wchar_t *a, wchar_t *b));



/**	String comparison.
	@param	a	Left string.
	@param	b	Right string.
	@return	Comparison result.
*/
EXTERN int
dkstr_w_cmp DK_PR((wchar_t *a, wchar_t *b));



/**	Get string length.
	@param	str	String to test.
	@return	Size of \a str (number of wchar_t).
*/
EXTERN size_t
dkstr_w_len DK_PR((wchar_t *str));



/**	Copy string.
	@param	d	Destination pointer.
	@param	s	Source pointer.
*/
EXTERN void
dkstr_w_cpy DK_PR((wchar_t *d, wchar_t *s));



/**	Duplicate string.
	@param	str	String to duplicate.
	@return	Pointer to duplicate in dynamically allocated memory.
	Use dk_delete() to release the memory. On error the function
	returns NULL.
*/
EXTERN wchar_t *
dkstr_w_dup DK_PR((wchar_t *str));



/**	Explode one large string to multiple small strings.
	@param	array	Array of pointers.
	@param	sz	Size of \a array (number of elements).
	@param	str	Source string.
	@param	whsp	Set of whitespaces.
	@return	Number of substrings found.
*/
EXTERN size_t
dkstr_w_explode DK_PR((wchar_t **array, size_t sz, wchar_t *str, wchar_t *whsp));


#if defined(__cplusplus)
}
#endif

#endif
/* DK_STR_INCLUDED */


