/****************************************************************************/
/*	Copyright (c) 2009, Bendor Research Pty. Ltd. All rights reserved.		*/
/*	This software is released under the GNU General Public License, version	*/
/*	3, with the exemptions that 1) the header files installed by this 	 	*/
/*	package can be included in closed-source code and 2) the libraries		*/
/*	built by this package can be statically linked into a closed-source 	*/
/*	binary. See the file LICENSE for the details.							*/
/*	This software is provided "AS IS", without any warranty or guarantee.	*/
/*	By using this software you acknowledge that neither Bendor Research nor	*/
/*	any of its personnel or affiliates can be held liable for any damages,	*/
/*	including, but not limited to, loss of business, loss of money, loss of */
/*	life, loss or reputation, arising out of this software being faulty or	*/
/*	not performing as advertised, even if Bendor Research was aware of such	*/
/*	faults in the software. You use this software at your own risk, any and */
/*	all liabilities that arise out of your using this software are strictly	*/
/*	yours.																	*/
/****************************************************************************/

#ifndef _STRING_H
#define	_STRING_H

#include <stddef.h>

size_t	strlcpy( char *dst, const char *src, size_t len );
size_t	strlcat( char *dst, const char *src, size_t len );
size_t	strspn( const char *str, const char *set );
size_t	strcspn( const char *str, const char *set );
char	*strpbrk( const char *str, const char *set );
char	*strsep( char **string, const char *delim );
char	*strstr( const char *haystack, const char *needle );
size_t	strlen_fast( const char *s );
size_t	strnlen_fast( const char *s, size_t n );
char	*strcpy_fast( char *dst, const char *src );
char	*strncpy_fast( char *dst, const char *src, size_t len );
char	*strcat_fast( char *s1, const char *s2 );
void	*memset_fast( void *p, int c, size_t n );
void	*memrcpy_fast( void *dst, const void *src, size_t len );
void	*memmove_fast( void *dst, void *src, size_t len );
void	*memcpy_fast( void *dst, const void *src, size_t len );
int		memcmp_fast( const void *p1, const void *p2, size_t n );

#ifndef BLC_STRING_INLINE

	void	*memset( void *p, int c, size_t n );
	void	*memcpy( void *dst, const void *src, size_t len );
	void	*memrcpy( void *dst, const void *src, size_t len );
	void	*memccpy( void *d, const void *s, int c, size_t n );
	void	*memmove( void *dst, void *src, size_t len );
	int		memcmp( const void *p1, const void *p2, size_t n );
	void	*memchr( const void *p, int c, size_t n );
	void	*memrchr( const void *p, int c, size_t n );
	size_t	strlen( const char *s );
	size_t	strnlen( const char *s, size_t n );
	char	*strcpy( char *dst, const char *src );
	char	*strncpy( char *dst, const char *src, size_t n );
	char	*strcat( char *s1, const char *s2 );
	char	*strncat( char *s1, const char *s2, size_t n );
	int		strcmp( const char *a, const char *b );
	int		strncmp( const char *a, const char *b, size_t n );
	char	*strchr( const char *s, int c );
	char	*strrchr( const char *s, int c );

#else

	#if ! defined __GNUC_STDC_INLINE__ && ! defined __GNUC_GNU_INLINE__
		#if defined __STRICT_ANSI__ && __STRICT_ANSI__
			#define __GNUC_STDC_INLINE__ 1
		#else
			#define __GNUC_GNU_INLINE__ 1
		#endif
	#endif
	#if defined __GNUC_STDC_INLINE__ && __GNUC_STDC_INLINE__
		#define _static	static
	#else
		#define	_static extern
	#endif

	_static void	*memset( void *p, int c, size_t n );
	_static void	*memcpy( void *dst, const void *src, size_t len );
	_static void	*memrcpy( void *dst, const void *src, size_t len );
	_static void	*memccpy( void *d, const void *s, int c, size_t n );
	_static void	*memmove( void *dst, void *src, size_t len );
	_static int		memcmp( const void *p1, const void *p2, size_t n );
	_static void	*memchr( const void *p, int c, size_t n );
	_static void	*memrchr( const void *p, int c, size_t n );
	_static size_t	strlen( const char *s );
	_static size_t	strnlen( const char *s, size_t n );
	_static char	*strcpy( char *dst, const char *src );
	_static char	*strncpy( char *dst, const char *src, size_t n );
	_static char	*strcat( char *s1, const char *s2 );
	_static char	*strncat( char *s1, const char *s2, size_t n );
	_static int		strcmp( const char *a, const char *b );
	_static int		strncmp( const char *a, const char *b, size_t n );
	_static char	*strchr( const char *s, int c );
	_static char	*strrchr( const char *s, int c );

	_static __inline__ void	*memccpy( void *d, const void *s, int c, size_t n )
	{
	unsigned char *dp = (unsigned char *) d;
	unsigned char *sp = (unsigned char *) s;

		c &= 255;

		while ( n-- )

			if ( ( *dp++ = *sp++ ) == c )

				return( dp );

		return( NULL );
	}

	_static __inline__ void	*memchr( const void *p, int c, size_t n )
	{
	unsigned char	*s;

		for ( s = (unsigned char *) p, c &= 255 ; n-- ; )

			if ( *s++ == c ) return( s - 1 );

		return( NULL );
	}

	_static __inline__ int	memcmp( const void *p1, const void *p2, size_t n )
	{
	unsigned char	a, *ap;
	unsigned char	b, *bp;

		ap = (unsigned char *) p1;
		bp = (unsigned char *) p2;

		while ( n-- ) {

			a = *ap++;
			b = *bp++;
			if ( a != b ) return( a - b );
		}

		return( 0 );
	}

	_static __inline__ void	*memcpy( void *dst, const void *src, size_t len )
	{
	char	*s = (char *) src;
	char	*d = (char *) dst;

		while ( len-- ) *d++ = *s++;
		return( dst );
	}

	_static __inline__ void	*memrcpy( void *dst, const void *src, size_t len )
	{
	char	*s = (char *) src + len;
	char	*d = (char *) dst + len;

		while ( len-- ) *--d = *--s;
		return( dst );
	}

	_static __inline__ void	*memmove( void *dst, void *src, size_t len )
	{
	char	*s, *d;

		s = (char *) src;
		d = (char *) dst;

		if ( d < s ) {

			while ( len-- ) *d++ = *s++;
		}
		else {

			d += len;
			s += len;
			while ( len-- ) *--d = *--s;
		}

		return( dst );
	}

	_static __inline__ void	*memrchr( const void *p, int c, size_t n )
	{
	unsigned char	*s;

		for ( s = (unsigned char *) p + n, c &= 255 ; n-- ; )

			if ( *--s == c ) return( s );

		return( NULL );
	}

	_static __inline__ void	*memset( void *s, int c, size_t n )
	{
	char	*p = s;

		while ( n-- ) *p++ = c;
		return( s );
	}

	_static __inline__ int	strcmp( const char *s1, const char *s2 )
	{
	unsigned char	a, b;
	int				c;

		for ( ;; ) {

			a = *s1++;
			b = *s2++;
			c = a - b;
			if ( a == 0 || a != b ) return( c );
		}
	}

	_static __inline__ char	*strcpy( char *dst, const char *src )
	{
	char	*ret = dst;

		while ( ( *dst++ = *src++ ) );
		return( ret );
	}

	_static __inline__ size_t	strlen( const char *s )
	{
	const	char	*p = s + 1;

		while ( *s++ );
		return( s - p );
	}

	_static __inline__ char	*strcat( char *dst, const char *src )
	{
		strcpy( dst + strlen( dst ), src );
		return( dst );
	}

	_static __inline__ char	*strncat( char *dst, const char *src, size_t len )
	{
	char	*tmp;

		tmp = dst + strlen( dst );

		while ( len-- )

			if ( ! ( *tmp++ = *src++ ) )

				return( dst );

		*tmp = '\0';
		return( dst );
	}

	_static __inline__ int	strncmp( const char *s1, const char *s2, size_t ml )
	{
	unsigned char	a, b;
	int				c;

		while ( ml-- ) {

			a = *s1++;
			b = *s2++;
			c = a - b;
			if ( a == 0 || a != b ) return( c );
		}

		return( 0 );
	}

	_static __inline__ char	*strncpy( char *dst, const char *src, size_t len )
	{
	char	*ret = dst;

		while ( len-- && ( *dst++ = *src++ ) );
		while ( len-- ) *dst++ = 0;
		return( ret );
	}

	_static __inline__ size_t	strnlen( const char *s, size_t m )
	{
	const	char	*p = s;

		for ( ;; ) {

			if ( ! m-- ) return( s - p );
			if ( ! *s++ ) return( s - p - 1 );
		}
	}

	_static __inline__ char	*strchr( const char *s, int c )
	{
	unsigned char	t;

		c &= 255;

		for ( ;; ) {

			t = *s++;
			if ( ! t ) return( NULL );
			if ( t == c ) return( (char *) s - 1 );
		}
	}

	_static __inline__ char	*strrchr( const char *s, int c )
	{
	unsigned char	t;
	char			*l = NULL;

		c &= 255;

		for ( ;; ) {

			t = *s++;
			if ( ! t ) return( l );
			if ( t == c ) l = (char *) s - 1;
		}
	}

	#undef _static

#endif

#ifdef BLC_STRING_FAST
	#define	memcmp		memcmp_fast
	#define	memset		memset_fast
	#define	memcpy		memcpy_fast
	#define	memrcpy		memrcpy_fast
	#define	memmove		memmove_fast
	#define	strcat		strcat_fast
	#define	strcpy		strcpy_fast
	#define	strlen		strlen_fast
	#define	strncpy		strncpy_fast
	#define	strnlen		strnlen_fast
#endif

#endif

