Newer
Older
rtlibc / src / string.c
@Razvan Turiac Razvan Turiac on 19 Dec 2019 9 KB Improved code.
#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)
{
	if (num)
	{
		const uint8_t *src_ptr8 = (const uint8_t*)src;
		uint8_t *dest_ptr8 = (uint8_t*)dest;	
		uint8_t * const dest_ptr8_end = dest_ptr8 + num;
		
		if (((uintptr_t)src_ptr8 & 0x03) == ((uintptr_t)dest_ptr8 & 0x03))		//if we have the same alignment
		{
			uint8_t *end = (uint8_t*)(((uintptr_t)dest_ptr8 + 3) & ~0x3);
			if (end > dest_ptr8_end)
				end = dest_ptr8_end;
		
			while(dest_ptr8 < end)
				*dest_ptr8++ = *src_ptr8++;
		
			uint32_t *dest_ptr32 = (uint32_t*)dest_ptr8;
			const uint32_t *src_ptr32 = (const uint32_t*)src_ptr8;
			uint32_t * const dest_ptr32_end = (uint32_t*)((uintptr_t)dest_ptr8_end & ~0x3);
			while(dest_ptr32 < dest_ptr32_end)
				*dest_ptr32++ = *src_ptr32++;

			dest_ptr8 = (uint8_t*)dest_ptr32;
			src_ptr8 = (uint8_t*)src_ptr32;
			while(dest_ptr8 < dest_ptr8_end)
				*dest_ptr8++ = *src_ptr8++;
		}
		else
		{
			while(dest_ptr8 < dest_ptr8_end)
				*dest_ptr8++ = *src_ptr8++;
		}
	}

	return dest;
}

void* memmove(void *dest, const void *src, size_t num)
{
	if (dest == src)
		return dest;
		
	uint8_t *src_p8 = (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)
{
	if (num)
	{
		uint8_t *dest_ptr8 = (uint8_t*)ptr;	
		uint8_t * const dest_ptr8_end = dest_ptr8 + num;
		const uint32_t value32 = ((uint32_t)value << 24) + ((uint32_t)value << 16) + ((uint32_t)value << 8) + (uint32_t)value;
		
		uint8_t *end = (uint8_t*)(((uintptr_t)dest_ptr8 + 3) & ~0x3);
		if (end > dest_ptr8_end)
			end = dest_ptr8_end;
		while(dest_ptr8 < end)
			*dest_ptr8++ = value;
	
		uint32_t *dest_ptr32 = (uint32_t*)dest_ptr8;
		uint32_t * const dest_ptr32_end = (uint32_t*)((uintptr_t)dest_ptr8_end & ~0x3);
		while(dest_ptr32 < dest_ptr32_end)
			*dest_ptr32++ = value32;

		dest_ptr8 = (uint8_t*)dest_ptr32;
		while(dest_ptr8 < dest_ptr8_end)
			*dest_ptr8++ = 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;
}