/* Various methods for dealing with strings. 29-12-2004 */

#include <stdlib.h>

/***************************************************************************
 * Returns a new string that is a substring of the string specified. The
 * substring begins at the specified beginIndex and extends to the character
 * at index endIndex - 1.
 * Thus the length of the substring is endIndex-beginIndex.
 *
 * @beginIndex : the beginning index, inclusive.
 * @endIndex   : the ending index, exclusive.
 ***************************************************************************/
char *strSubstring(const char *str, int beginIndex, int endIndex) {

	int i;
	char *substr, *temp;

	if( beginIndex < 0 || endIndex > strLength(str) || endIndex < beginIndex )
		return NULL;

	if( (substr = (char *)malloc((endIndex-beginIndex)*sizeof(char))) == NULL )
		return NULL;

	temp = (char *)&str[beginIndex];

	for(i=0; i < (endIndex-beginIndex); i++)
		substr[i] = temp[i];

	substr[i] = '\0';

	return substr;

}

/*****************************************************************************
 * Splits the string specified around matches of the given regular expression.
 *
 * @regex: the delimiting regular expression.
 *****************************************************************************/
char **strSplit(const char *str, const char *regex) {

	char *buf, **splitted;
	int j=0, pos;

	if( (splitted = (char **)malloc(strLength(str)*sizeof(char *))) == NULL )
		return NULL;

	buf = (char *)str;
	while( (pos = strIndexOf(buf, regex)) > -1 ) {
		splitted[j++] = (char *)strSubstring(buf, 0, pos);
		buf = &buf[pos + strLength(regex)];
	}

	splitted[j++] = (char *)strSubstring(buf, 0, strLength(buf));
	splitted[j] = '\0';

	return splitted;

}

/***********************************************************************
 * Returns the index within the string specified of the first occurrence
 * of the specified substring. If it does not occur, -1 is returned.
 *
 * @str    : the string to be searched.
 * @substr : the string to search for.
 ***********************************************************************/
int strIndexOf(const char *str, const char *substr) {
	int i=0, flag;
	char *ptr1, *ptr2;

	do {
		ptr1=(char *)&str[i++];
		ptr2=(char *)substr;

		flag=0;

		while(*ptr2 != '\0') {
			if(*ptr1++ != *ptr2++) flag=1;
		}
		if(flag==0) return(i-1);
	}while(*ptr1 != '\0');

	return(-1);
}

/***************************************************************************
 * Returns 1 if and only if string str contains the specified string substr.
 *
 * @str    : the string to be searched.
 * @substr : the string to search for.
 ***************************************************************************/
int strContains(const char *str, const char *substr) {

	if(strIndexOf(str, substr) > -1)
		return 1;

	return 0;

}

/*************************************************************************
 * Replaces the first substring of the string str that matches the given
 * regular expression with the given replacement.
 *
 * @regex :  the regular expression to which this string is to be matched.
 *************************************************************************/
char *strReplaceFirst(const char *str, const char *regex, const char *replacement) {

	int i, j, index, tmp;
	char *resultString, *buf;

	index = strIndexOf(str, regex);

	if(index < 0)
		return NULL;

	resultString = (char *)malloc(strLength(str) + strLength(replacement) - strLength(regex));
	
	if( resultString == NULL )
		return NULL;

	buf = (char *)str;
	for(i=0; i<index; i++)
		resultString[i] = *buf++;

	tmp = strLength(replacement);
	for(j=0; j<tmp; j++, i++)
		resultString[i] = replacement[j];

	tmp = strLength(regex);
	for(j=0; j<tmp; j++)
		buf++;

	tmp = strLength(buf);
	for(j=0; j<tmp; j++, i++)
		resultString[i] = buf[j];

	resultString[i] = '\0';

	return resultString;

}

/************************************************************************
 * Replaces each substring of the string str that matches the given
 * regular expression with the given replacement.
 *
 * @regex : the regular expression to which this string is to be matched.
 ************************************************************************/
char *strReplaceAll(const char *str, const char *regex, const char *replacement) {

	char *curr, *prev = NULL;

	curr = (char *)str;
	do {
		if (prev != NULL) {
			free(prev); prev = NULL;
		}
		prev = curr;
		curr = strReplaceFirst(curr, regex, replacement);
	}while(curr != NULL);

	return prev;

}

/*************************************************************************
 * Returns the length of this string. The length is equal to the number of
 * characters in the string.
 *
 * @str : The string to be sized.
 *************************************************************************/
int strLength(const char *str) {

	const char *buf;

	for (buf = str; *buf != '\0'; buf++);

	return buf - str;

}

