
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <stddef.h>
#include <syslog.h>
#include <stdio.h>

#include "pldstr.h"


/*------------------------------------------------------------------------
 Procedure:     PLD_strncpy ID:1
 Purpose:       Copy characters from 'src' to 'dst', writing not more than 'len'
                characters to the destination, including the terminating \0.
                Thus, for any effective copying, len must be > 1.
 Input:         char *dst: Destination string
                char *src: Source string
                size_t len: length of string
 Output:        Returns a pointer to the destination string.
 Errors:
------------------------------------------------------------------------*/
char *PLD_strncpy (char *dst, const char *src, size_t len)
{
	char *dp = dst;
	const char *sp = src;

	if (len == 0) return dst;

	// Compensate for the fact that we have to add a \0 at the end of our buffer
	// no matter WHAT!

//	if (len == sizeof(void *)) syslog(1,"WARNING: Possible pointer size being sent");

	while ((len) && (*sp != '\0'))
	{
		*dp++ = *sp++;
		len--;
	}

	*dp = '\0';

	return dst;
}


char *PLD_strncat( char *dst, const char *src, size_t len )
{
	char *dp = dst;
	const char *sp = src;
	int cc;

	if (len == 0) return dst;

	len--;

	// Locate the end of the current string.
	cc = 0;
	while ((*dp)&&(cc < len)) { dp++; cc++; }

	// If we have no more buffer space, then return the destination

	if (cc >= len) return dst;

	// While we have more source, and there's more char space left in the buffer

	while ((*sp)&&(cc < len))
	{
		cc++;
		*dp = *sp;
		dp++;
		sp++;
	}

	// Terminate dst, as a gaurantee of string ending.

	*dp = '\0';

	return dst;
}


char *PLD_strncate( char *dst, const char *src, size_t len, char *endpoint )
{
	char *dp = dst;
	const char *sp = src;
	int cc = 0;

	if (len == 0) return dst;

	len--;

	// If endpoint does not relate correctly, then force manual detection
	// of the endpoint.

	if ((!endpoint)||(endpoint == dst)||((endpoint -dst +1)>len))
	{
		// Locate the end of the current string.
		cc = 0;
		while ((*dp != '\0')&&(cc < len)) { dp++; cc++; }
	}
	else {
		cc = endpoint -dst +1;
		dp = endpoint;
	}

	// If we have no more buffer space, then return the destination

	if (cc >= len) return dst;

	// While we have more source, and there's more char space left in the buffer

	while ((*sp)&&(cc < len))
	{
		cc++;
		*dp = *sp;
		dp++;
		sp++;
	}

	// Terminate dst, as a gaurantee of string ending.

	*dp = '\0';

	return dst;
}





/*------------------------------------------------------------------------
Procedure:     XAM_strncasecmp ID:1
Purpose:       Portable version of strncasecmp(), this may be removed in later
versions as the strncase* type functions are more widely
implemented
Input:
Output:
Errors:
------------------------------------------------------------------------*/
int PLD_strncasecmp( char *s1, char *s2, int n )
{
	char *ds1 = s1, *ds2 = s2;
	char c1, c2;
	int result = 0;

	while(n > 0)
	{
		c1 = tolower(*ds1);
		c2 = tolower(*ds2);

		if (c1 == c2)
		{
			n--;
			ds1++;
			ds2++;
		}
		else
		{
			result = c2 - c1;
			n = 0;
		}

	}

	return result;

}





/*------------------------------------------------------------------------
Procedure:     XAM_strtok ID:1
Purpose:       A thread safe version of strtok()
Input:
Output:
Errors:
------------------------------------------------------------------------*/
char *PLD_strtok( struct PLD_strtok *st, char *line, char *delimeters )
{
	char *stop;
	char *dc;
	char *result = NULL;

	if ( line )
	{
		st->start = line;
	}

	//Strip off any leading delimeters

	dc = delimeters;
	while ((st->start)&&(*dc != '\0'))
	{
		if (*dc == *(st->start))
		{
			st->start++;
			dc = delimeters;
		}
		else dc++;
	}

	// Where we are left, is the start of our token.

	result = st->start;

	//	fprintf(stdout,"DEBUG:%d: start = '%s', delimeters = '%s'\n",__LINE__,st->start, delimeters);

	if ((st->start)&&(st->start != '\0'))
	{
		stop = strpbrk( st->start, delimeters ); /* locate our next delimeter */

		// If we found a delimeter, then that is good.  We must now break the string here
		// and don't forget to store the character which we stopped on.  Very useful bit
		// of information for programs which process expressions.

		if (stop)
		{

			// Store our delimeter.

			st->delimeter = *stop;

			// Terminate our token.

			*stop = '\0';


			// Because we're emulating strtok() behaviour here, we have to
				// absorb all the concurrent delimeters, that is, unless we
				// reach the end of the string, we cannot return a string with
				// no chars.

			stop++;
			dc = delimeters;
			while (*dc != '\0')
			{
				if (*dc == *stop)
				{
					stop++;
					dc = delimeters;
				}
				else dc++;
			} // While

			//			fprintf(stdout,"Loop end: stop = '%c'\n",*stop);

			if (*stop == '\0') st->start = NULL;
			else st->start = stop;

		}
		else {
			st->start = NULL;
			st->delimeter = '\0';
		}
	}
	else  {
		st->start = NULL;
		result = NULL;
	}


	return result;
}



/*------------------------------------------------------------------------
 Procedure:     PLD_strlower ID:1
 Purpose:       Converts a string to lowercase
 Input:         char *convertme : string to convert
 Output:
 Errors:
------------------------------------------------------------------------*/
int PLD_strlower( unsigned char *convertme )
{

	// Updates:
	//	09-11-2002 - changed from 'char *' to 'unsigned char *' to deal with
	//		non-ASCII characters ( ie, french ).  Pointed out by Emmanuel Collignon

	unsigned char *c = convertme;

	while ( *c != '\0') {*c = tolower(*c); c++;}

	return 0;
	}





//-----------------END.
