Newer
Older
rtlibc / src / string.c
#include <string.h>
#include <ctype.h>


//String manipulation functions

void strtrim(char **str, const char *trim)
{
	//skip all the delimiter chars at the beginning
	while(**str && strchr(trim, **str))
		(*str)++;

	//if we still have a non null string, trim from the back
	if (**str)
	{
		char *end = *str + strlen(*str);
		while(strchr(trim, *(--end)));
		*(++end) = 0;
	}
}


size_t strlen(const char *str)
{
	size_t s = 0;

	while(*str++)
		s++;

	return s;
}


size_t strnlen(const char *str, size_t num)
{
	size_t s = 0;

	while(*str++ && num--)
		s++;

	return s;
}


size_t wstrlen(const uint16_t *str)
{
	size_t s = 0;

	while(*str++)
		s++;

	return s;
}


char* strcat(char *dest, const char *src)
{
	char *rv = dest;
	
	while(*dest)
		dest++;

	do
	{
		*dest++ = *src;
	}while(*src++);

	return rv;	
}


char* strncat(char *dest, const char *src, size_t num)
{
	char *rv = dest;
	
	while(*dest)
		dest++;

	while(*src && num--)
	{
		*dest++ = *src++;
	}
		
	*dest = 0;

	return rv;	
}


char* strchr(const char *str, char c)
{
	while(*str)
	{
		if (*str == c)
			return (char*)str;
		
		str++;
	}
	
	if (*str == c)
		return (char*)str;
	else
		return 0;
}


int strcmp(const char *str1, const char *str2)
{
	while(*str1 && *str2)
	{
		if ((*str1) > (*str2))
			return 1;
		else if ((*str1) < (*str2))
			return -1;

		str1++;
		str2++;	
	}
	
	if (*str1)
		return 1;
	else if (*str2)
		return -1;
		
	return 0;
}


int strncmp(const char *str1, const char *str2, size_t num)
{
	while(*str1 && *str2 && num)
	{
		if ((*str1) > (*str2))
			return 1;
		else if ((*str1) < (*str2))
			return -1;

		str1++;
		str2++;

		num--;
	}

	if (num == 0)
		return 0;	
	else if (*str1)
		return 1;
	else if (*str2)
		return -1;
		
	return 0;
}


int stricmp(const char *str1, const char *str2)
{
	while(*str1 && *str2)
	{
		if (tolower(*str1) > tolower(*str2))
			return 1;
		else if (tolower(*str1) < tolower(*str2))
			return -1;

		str1++;
		str2++;	
	}
	
	if (*str1)
		return 1;
	else if (*str2)
		return -1;
		
	return 0;
}



int strincmp(const char *str1, const char *str2, size_t num)
{
	while(*str1 && *str2 && num)
	{
		if (tolower(*str1) > tolower(*str2))
			return 1;
		else if (tolower(*str1) < tolower(*str2))
			return -1;

		str1++;
		str2++;	

		num--;
	}
	
	if (num == 0)
		return 0;
	else if (*str1)
		return 1;
	else if (*str2)
		return -1;
		
	return 0;
}



char* strcpy(char *dest, const char *src)
{
	char *rv = dest;
	do
	{
		*dest++ = *src;
	}while(*src++);

	return rv;
}


char* strncpy(char *dest, const char *src, size_t num)
{
	char *rv = dest;

	while(*src && num)
	{
		*dest++ = *src++;
		num--;
	}

	while(num--)
		*dest++ = 0;
		
	return rv;
}



size_t strspn(const char *str1, const char *str2)
{
	size_t span = 0;
	
	while(*str1 && strchr(str2, *str1))
	{
		str1++;
		span++;
	}

	return span;
}


size_t strcspn(const char *str1, const char *str2)
{
	size_t span = 0;
	
	while(*str1 && !strchr(str2, *str1))
	{
		str1++;
		span++;
	}

	return span;
}



//char *strdup(const char *s1);


//const char* strpbrk(const char *str1, const char *str2);
char* strpbrk(char *str1, const char *str2)
{
	while(*str1)
	{
		if (strchr(str2, *str1))
			return str1;
		str1++;
	}
	return 0;
}


/*
const char* strstr(const char *str1, const char *str2)
{
	const char *ptr1 = str1;
	const char *ptr2 = str2;
			
	while(*str1)
	{
		if (*ptr2 == 0)
			return str1;
			
		if (*ptr1 == *ptr2)
		{
			ptr1++;
			ptr2++;
		}
		else
		{
			ptr2 = str2;
			str1++;
			ptr1 = str1;
		}
	}

	return 0;
}
*/


char* strstr(char *str1, const char *str2)
{
	char *ptr1 = str1;
	const char *ptr2 = str2;
			
	while(*str1)
	{
		if (*ptr2 == 0)
			return str1;
			
		if (*ptr1 == *ptr2)
		{
			ptr1++;
			ptr2++;
		}
		else
		{
			ptr2 = str2;
			str1++;
			ptr1 = str1;
		}
	}

	return 0;
}			


char* stristr(char *str1, const char *str2)
{
	char *ptr1 = str1;
	const char *ptr2 = str2;
			
	while(*str1)
	{
		if (*ptr2 == 0)
			return str1;
			
		if (tolower(*ptr1) == tolower(*ptr2))
		{
			ptr1++;
			ptr2++;
		}
		else
		{
			ptr2 = str2;
			str1++;
			ptr1 = str1;
		}
	}

	return 0;
}			
			

char* strtok(char *str, const char *delim)
{
	static char *saveptr;
	
	if (str)
		saveptr = str;
	
	if (*saveptr == 0)
		return 0;
		
	//find first non-delimiter
	while(*saveptr && strchr(delim, *saveptr))
		saveptr++;
	
	char *result = saveptr;

	while(*saveptr && !strchr(delim, *saveptr))
		saveptr++;
		
	if (*saveptr)
		*saveptr++ = 0;
	
	return result;
}


char* strtok_r(char *str, const char *delim, char **saveptr)
{
	if (str)
		*saveptr = str;
	
	if (**saveptr == 0)
		return 0;
		
	//find first non-delimiter
	while(**saveptr && strchr(delim, **saveptr))
		(*saveptr)++;
	
	char *result = *saveptr;

	while(**saveptr && !strchr(delim, **saveptr))
		(*saveptr)++;
		
	if (**saveptr)
		*(*saveptr)++ = 0;
	
	return result;
}



char* strtok_m(char *str, const char *delim, const char* token_markers)
{
	static char *saveptr;
	
	if (str)
		saveptr = str;
	
	if (*saveptr == 0)
		return 0;

	const size_t stm = strlen(token_markers);
	uint8_t tm_count[stm];
	
	memset(tm_count, 0, sizeof(tm_count));

	//find first non-delimiter
	while(*saveptr && strchr(delim, *saveptr))
		saveptr++;
		
	char *result = saveptr;
	uint8_t inside = 0;

	while(*saveptr)
	{
		char *ptr;
		
		ptr = strchr(token_markers, *saveptr);
		if (ptr)
		{
			ptrdiff_t i = ptr - token_markers;
			tm_count[i] = !tm_count[i];
			
			inside = 0;
			for(uint32_t i = 0; i < stm; i++)
				if (tm_count[i])
				{
					inside = 1;
					break;
				}
		}
		else
		{
			//check if inside token marker
			if (!inside && strchr(delim, *saveptr))
				break;
		}

		saveptr++;
	}

	if (*saveptr)
		*saveptr++ = 0;

	return result;
}


char* strtok_rm(char *str, const char *delim, char **saveptr, const char* token_markers)
{
	if (str)
		*saveptr = str;
	
	if (**saveptr == 0)
		return 0;

	const size_t stm = strlen(token_markers);
	uint8_t tm_count[stm];
	
	memset(tm_count, 0, sizeof(tm_count));

	//find first non-delimiter
	while(**saveptr && strchr(delim, **saveptr))
		(*saveptr)++;
		
	char *result = *saveptr;
	uint8_t inside = 0;

	while(**saveptr)
	{
		char *ptr;
		
		ptr = strchr(token_markers, **saveptr);
		if (ptr)
		{
			ptrdiff_t i = ptr - token_markers;
			tm_count[i] = !tm_count[i];
			
			inside = 0;
			for(uint32_t i = 0; i < stm; i++)
				if (tm_count[i])
				{
					inside = 1;
					break;
				}
		}
		else
		{
			if (!inside && strchr(delim, **saveptr))
				break;
		}

		(*saveptr)++;
	}

	if (**saveptr)
		*(*saveptr)++ = 0;

	return result;
}



//memory functions
void* memcpy(void* dest, const void* src, size_t num)
{
#define BLOCK_SIZE (sizeof(uint32_t) << 2)

	if (num)
	{
		const uint8_t* sptr = (const uint8_t*)src;
		uint8_t* dptr = (uint8_t*)dest;	

		if ((num >= BLOCK_SIZE) &&
			(((uintptr_t)sptr & (sizeof(uint32_t) - 1)) == 0) &&
			(((uintptr_t)dptr & (sizeof(uint32_t) - 1)) == 0))
		{
			const uint32_t* sptr_aligned = (const uint32_t*)sptr;
			uint32_t* dptr_aligned = (uint32_t*)dptr;

			while(num >= BLOCK_SIZE)
			{
				*dptr_aligned++ = *sptr_aligned++;
				*dptr_aligned++ = *sptr_aligned++;
				*dptr_aligned++ = *sptr_aligned++;
				*dptr_aligned++ = *sptr_aligned++;

				num -= BLOCK_SIZE;
			}

			while(num >= sizeof(uint32_t))
			{
				*dptr_aligned++ = *sptr_aligned++;
				num -= sizeof(uint32_t);
			}


			sptr = (const uint8_t*)sptr_aligned;
			dptr = (uint8_t*)dptr_aligned;	
		}
		
		while(num--)
			*dptr++ = *sptr++;
	}

	return dest;
}

void* memmove(void* dest, const void* src, size_t num)
{
	if (dest == src)
		return dest;
		
	const uint8_t* src_p8 = (const uint8_t*)src;
	uint8_t* dest_p8 = (uint8_t*)dest;
		
	if (src < dest)
	{
		//copy from back
		src_p8 += num - 1;
		dest_p8 += num - 1;

		while(num--)
			*dest_p8-- = *src_p8--;
	}
	else
	{
		//copy from front
		while(num--)
			*dest_p8++ = *src_p8++;
	}
	
	return dest;
}


//const void* memchr(const void *ptr, uint8_t value, size_t num);
//void* memchr(void *ptr, uint8_t value, size_t num);

int memcmp(const void* ptr1, const void* ptr2, size_t num)
{
	const uint8_t* l_ptr8 = (const uint8_t*)ptr1;
	const uint8_t* r_ptr8 = (const uint8_t*)ptr2;

	while(num--)
	{
		if (*l_ptr8 > *r_ptr8)
			return 1;
		else if (*l_ptr8 < *r_ptr8)
			return -1;

		l_ptr8++;
		r_ptr8++;
	}

	return 0;
}


void* memset(void* ptr, uint8_t value, size_t num)
{
#define BLOCK_SIZE (sizeof(uint32_t) << 2)

	if (num)
	{
		uint8_t* dptr = (uint8_t*)ptr;	

		if ((num >= BLOCK_SIZE) &&
			(((uintptr_t)dptr & (sizeof(uint32_t) - 1)) == 0))
		{
			const uint32_t value32 = ((uint32_t)value << 24) + ((uint32_t)value << 16) + ((uint32_t)value << 8) + (uint32_t)value;
			uint32_t* dptr_aligned = (uint32_t*)dptr;

			while(num >= BLOCK_SIZE)
			{
				*dptr_aligned++ = value32;
				*dptr_aligned++ = value32;
				*dptr_aligned++ = value32;
				*dptr_aligned++ = value32;

				num -= BLOCK_SIZE;
			}

			while(num >= sizeof(uint32_t))
			{
				*dptr_aligned++ = value32;
				num -= sizeof(uint32_t);
			}

			dptr = (uint8_t*)dptr_aligned;	
		}
		
		while(num--)
			*dptr++ = value;
	}
	
	return ptr;
}


const char* strfile(const char *fullpath)
{
	const char *ptr = fullpath + strlen(fullpath);
	
	while(ptr >= fullpath)
	{
		if (*ptr == '/')
			return ptr + 1;

		ptr--;
	}

	return fullpath;
}