Newer
Older
rtlibc / src / stdlib.c
@Razvan Turiac Razvan Turiac on 11 Sep 2023 6 KB ...
/* Copyright (C) Thornwave Labs Inc - All Rights Reserved
 * Unauthorized copying of this file, via any medium is strictly prohibited
 * Proprietary and confidential
 * Written by Razvan Turiac <razvan.turiac@thornwave.com>
 */

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

#include <malloc.h>

#include <assert.h>


static const char l_digits[] = "0123456789abcdef";


__attribute__((weak)) 
void rtlibc_abort_handler(void)
{
	
}


static inline uint8_t char2digit(char c)
{
	if (c >= 'a')
		return c - 'a' + 10;
	else if (c >= 'A')
		return c - 'A' + 10;
	else
		return c - '0';
}


uint64_t strtoul(const char *str, char **endptr, int32_t base)
{
	const int32_t max_base = 'Z' - 'A' + 11;
	
	if ((base > max_base) || (base < 0))
	{
		if (endptr)
			*endptr = (char*)str;
		return 0;
	}
	
	while(*str && isspace(*str))
		str++;
	
	if (*str == 0)
	{
		if (endptr)
			*endptr = (char*)str;
		return 0;
	}
	
	if (base == 0)
	{
		//autodetect the base
		if (*str == '0')
		{
			str++;
			if (*str == 0)
			{
				if (endptr)
					*endptr = (char*)str;
				return 0;
			}

			if ((*str == 'x') || (*str == 'X'))
			{
				base = 16;
				str++;
			}
			else
			{
				base = 8;
			}
		}
		else if (strchr("123456789", *str))
		{
			base = 10;
		}
		else
		{
			if (endptr)
				*endptr = (char*)str;
			return 0;
		}
	}

	//build allowed char list
	char charset[max_base + 1];
	char *ptr = charset;
	for(int32_t i = 0; i < base; i++)
	{
		if (i < 10)
			*ptr++ = i + '0';
		else
		{
			*ptr++ = i - 10 + 'A';
			*ptr++ = i - 10 + 'a';
		}
	}
	*ptr = 0;
	
	uint64_t val = 0;
	
	while(*str && strchr(charset, *str))
	{
		val *= base;
		val += char2digit(*str);
		str++;
	}
	
	if (endptr)
		*endptr = (char*)str;

	return val;
}



int64_t strtol(const char *str, char **endptr, int32_t base)
{
	const int32_t max_base = 'Z' - 'A' + 11;
	
	if ((base > max_base) || (base < 0))
	{
		if (endptr)
			*endptr = (char*)str;
		return 0;
	}
	
	while(*str && isspace(*str))
		str++;
	
	if (*str == 0)
	{
		if (endptr)
			*endptr = (char*)str;
		return 0;
	}
	
	bool negative = false;
	
	if (*str == '-')
	{
		negative = true;
		str++;
	}
	else if (*str == '+')
		str++;
	
	if (base == 0)
	{
		//autodetect the base
		if (*str == '0')
		{
			str++;
			if (*str == 0)
			{
				if (endptr)
					*endptr = (char*)str;
				return 0;
			}

			if ((*str == 'x') || (*str == 'X'))
			{
				base = 16;
				str++;
			}
			else
			{
				base = 8;
			}
		}
		else if (strchr("123456789", *str))
		{
			base = 10;
		}
		else
		{
			if (endptr)
				*endptr = (char*)str;
			return 0;
		}
	}

	//build allowed char list
	char charset[max_base + 1];
	char *ptr = charset;
	for(int32_t i = 0; i < base; i++)
	{
		if (i < 10)
			*ptr++ = i + '0';
		else
		{
			*ptr++ = i - 10 + 'A';
			*ptr++ = i - 10 + 'a';
		}
	}
	*ptr = 0;
	
	int64_t val = 0;
	
	while(*str && strchr(charset, *str))
	{
		val *= base;
		val += char2digit(*str);
		str++;
	}
	
	if (endptr)
		*endptr = (char*)str;
	
	if (negative)
		return -val;
	else
		return val;
}



float strtof(const char *str, char **endptr)
{
	while(*str && isspace(*str))
		str++;
	
	if (*str == 0)
	{
		if (endptr)
			*endptr = (char*)str;
		return 0;
	}
	
	bool negative = false;
	
	if (*str == '-')
	{
		negative = true;
		str++;
	}
	else if (*str == '+')
		str++;


	float val = 0;
	
	while(*str && strchr("0123456789", *str))
	{
		val *= 10;
		val += *str - '0';
		str++;
	}


	if (*str == '.')		//decimals follow
	{
		str++;
		
		uint64_t frac_value = 0;
		uint64_t frac_denominator = 1;
		
		while(*str && strchr("0123456789", *str))
		{
			frac_denominator *= 10;
			frac_value *= 10;
			frac_value += *str - '0';
			
			str++;
		}
		
		val += frac_value / (float)frac_denominator;

		if (*str)
		{
			if (endptr)
				*endptr = (char*)str;

			if (negative)
				return -val;
			else
				return val;		
		}
	}

	if (endptr)
		*endptr = (char*)str;
	
	if (negative)
		return -val;
	else
		return val;
}


int32_t atoi(const char* str)
{
	return (int32_t)strtol(str, NULL, 10);
}


int64_t atol(const char* str)
{
	return strtol(str, NULL, 10);
}


char* utoa(uint32_t n, char* buffer, uint32_t radix)
{
	if ((radix < 2) || (radix > 16))
		return buffer;

	char str[36];
	char* dptr = str + sizeof(str) - 1;
	*dptr = 0;

	while(n)
	{	
		*--dptr = l_digits[n % radix];
		n /= radix;
	}

	if (*dptr == 0)
		*--dptr = l_digits[0];

	strcpy(buffer, dptr);

	return buffer;
}


char* ultoa(uint64_t n, char* buffer, uint32_t radix)
{
	if ((radix < 2) || (radix > 16))
		return buffer;

	char str[72];
	char* dptr = str + sizeof(str) - 1;
	*dptr = 0;

	while(n)
	{	
		*--dptr = l_digits[n % radix];
		n /= radix;
	}

	if (*dptr == 0)
		*--dptr = l_digits[0];

	strcpy(buffer, dptr);

	return buffer;
}



char* itoa(int32_t n, char* buffer, uint32_t radix)
{
	if ((radix < 2) || (radix > 16))
		return buffer;

	char str[36];
	char* dptr = str + sizeof(str) - 1;
	*dptr = 0;

	const bool negative = (radix == 10) && (n < 0);

	uint32_t x = negative ? -n : n;

	while(x)
	{	
		*--dptr = l_digits[x % radix];
		x /= radix;
	}

	if (*dptr == 0)
		*--dptr = l_digits[0];

	if (negative)
		*--dptr = '-';

	strcpy(buffer, dptr);

	return buffer;
}


char* ltoa(int64_t n, char* buffer, uint32_t radix)
{
	if ((radix < 2) || (radix > 16))
		return buffer;

	char str[72];
	char* dptr = str + sizeof(str) - 1;
	*dptr = 0;

	const bool negative = (radix == 10) && (n < 0);

	uint64_t x = negative ? -n : n;

	while(x)
	{	
		*--dptr = l_digits[x % radix];
		x /= radix;
	}

	if (*dptr == 0)
		*--dptr = l_digits[0];

	if (negative)
		*--dptr = '-';

	strcpy(buffer, dptr);

	return buffer;
}




void abort(void)
{
	rtlibc_abort_handler();
}


static rtmalloc_context_t l_malloc_context;

__attribute__((weak)) 
void rtlibc_malloc_failed_handler(void)
{
}

void malloc_init(void *heap, size_t size, size_t alignment)
{
	assert(heap);
	assert(size);
	assert(alignment);
	rtmalloc_init(&l_malloc_context, heap, size, alignment);
}

__attribute__ ((weak))
void* malloc(size_t size)
{
	void *ptr = rtmalloc(&l_malloc_context, size);

	if (ptr == NULL)
		rtlibc_malloc_failed_handler();

	return ptr;
}

__attribute__ ((weak))
void free(void *p)
{
	assert(p);
	rtfree(&l_malloc_context, p);
}

size_t msize(void *p)
{
	assert(p);
	return rtmsize(&l_malloc_context, p);
}



__attribute__ ((weak))
void srand(uint32_t seed)
{

}

__attribute__ ((weak))
int32_t rand(void)
{
	return 0xDEADBEEF;
}

__attribute__((weak))
void getrandom(void* buffer, size_t size)
{
	uint8_t* ptr = (uint8_t*)buffer;
	
	while(size)
	{
		const size_t xfer_size = size < 4 ? size : 4;
		size -= xfer_size;

		const uint32_t r = rand();
		memcpy(ptr, &r, xfer_size);
		ptr += xfer_size;
	}
}