/*
 * string.c - string helper function implementation.
 *
 * Authors      Ghassan Almaless (2007,2009,2010,2011,2012)
 *              Alain Greiner (2017)
 *
 * Copyright (c) UPMC Sorbonne Universites
 *
 * This file is part of ALMOS-MKH.
 *
 * ALMOS-MKH is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2.0 of the License.
 *
 * ALMOS-MKH is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include <hal_types.h>
#include <ctype.h>
#include <string.h>

///////////////////////////////////
uint32_t strlen( const char * str )
{
	register const char *ptr = str;

	while (*ptr) ptr++;

	return (ptr - str);
}

///////////////////////////////////
uint32_t strnlen( const char * str,
                  uint32_t     maxlen )
{
	register const char *ptr = str;

	while (*ptr && (maxlen-- > 0)) ptr++;

	return (ptr - str);
}

////////////////////////////
int strcmp( const char * s1,
            const char * s2 )
{

	while (*s1 && *s1 == *s2)
	{
		s1 ++;
		s2 ++;
	}

	return (*s1 - *s2);
}

/////////////////////////////
int strncmp( const char * s1,
             const char * s2,
             uint32_t     n )
{ 
	if (n == 0)
		return s1 - s2; // XXX ???

	while (*s1 && (*s1 == *s2) && (n > 1))
	{
		s1 ++;
		s2 ++;
		n--;
	}

	return (*s1 - *s2);
}

//////////////////////////////////
int strcasecmp( const char * str1,
                const char * str2 )
{
	char c1;
	char c2;

	do{
		c1 = toupper(*++str1);
		c2 = toupper(*++str2);
	}while(c1 && c1 == c2);

	return (c1 - c2);
}

///////////////////////////
char * strcpy (char * dest,
               char * src )
{
	char *src_ptr = src;
	char *dst_ptr = dest;

	while(*src_ptr)
		*(dst_ptr++) = *(src_ptr++);

	*dst_ptr = 0;
	return dest;
}

///////////////////////////////
char * strncpy( char    * dest,
                char    * src,
                uint32_t  n )
{
	uint32_t i;

	for (i = 0; (i < n) && (src[i] != '\0') ; i++)
		dest[i] = src[i];

	for (; i < n; i++)
		dest[i] = '\0';

	return dest;
}

////////////////////////////////
char * strstr( char       * s,
               const char * find)
{
    char c, sc;
    size_t len;

    if ((c = *find++) != 0) {
        len = strlen(find);
        do {
            do {
                if ((sc = *s++) == 0)
                    return NULL;
            } while (sc != c);
        } while (strncmp(s, find, len) != 0);
        s--;
    }
    return s;
}

//////////////////////////////
char * strchr( const char * s,
               int          c )
{
	while(*s && *s != (char) c)
		s++;

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

	return NULL;
}

///////////////////////////////
char * strrchr( const char * t,
                int          c )
{
	register char         ch;
	register const char * l =0;

	ch = c;
	for (;;) {
		if (*t == ch)
			l=t;
		if (!*t)
			return (char*)l;
		++t;
	}
	return (char*)l;
}

/////////////////////////////////////
inline uint8_t to_lower( uint8_t  c )
{
   if (c >= 'A' && c <= 'Z') return (c | 0x20);
   else                      return c;
}


/////////////////////////////////////
inline uint8_t to_upper( uint8_t  c )
{
   if (c >= 'a' && c <= 'z') return (c & ~(0x20));
   else                      return c;
}


