Files
xomb-bare-bones/kernel/runtime/util.d

164 lines
3.8 KiB
D

// This module contains helpful functions found necessary by the runtime and gcc.
// contains: itoa, memcpy, memset, memmove, memcmp, strlen, isnan, toString
module kernel.runtime.util;
/**
This function converts an integer to a string, depending on the base passed in.
Params:
buf = The function will save the translated string into this character array.
base = The base of the integer value. If "d," it will be assumed to be decimal. If "x," the integer
will be hexadecimal.
d = The integer to translate.
Returns: The translated string in a character array.
*/
char[] itoa(char[] buf, char base, long d)
{
size_t p = buf.length - 1;
size_t startIdx = 0;
ulong ud = d;
bool negative = false;
int divisor = 10;
// If %d is specified and D is minus, put `-' in the head.
if(base == 'd' && d < 0)
{
negative = true;
ud = -d;
}
else if(base == 'x')
divisor = 16;
// Divide UD by DIVISOR until UD == 0.
do
{
int remainder = ud % divisor;
buf[p--] = (remainder < 10) ? remainder + '0' : remainder + 'a' - 10;
}
while (ud /= divisor)
if(negative)
buf[p--] = '-';
return buf[p + 1 .. $];
}
/**
This function copies data from a source piece of memory to a destination piece of memory.
Params:
dest = A pointer to the piece of memory serving as the copy destination.
src = A pointer to the piece of memory serving as the copy source.
count = The number of bytes to copy form src to dest.
Returns: A void pointer to the start of the destination data (dest).
*/
extern(C) void* memcpy(void* dest, void* src, size_t count)
{
ubyte* d = cast(ubyte*)dest;
ubyte* s = cast(ubyte*)src;
for(size_t i = count; count; count--, d++, s++)
*d = *s;
return dest;
}
/**
Memcpy and memmove only really have differences at the user level, where they have slightly
different semantics. Here, they're pretty much the same.
*/
extern(C) void* memmove(void* dest, void* src, size_t count)
{
ubyte* d = cast(ubyte*)dest;
ubyte* s = cast(ubyte*)src;
for(size_t i = count; count; count--, d++, s++)
*d = *s;
return dest;
}
/**
Compare two blocks of memory.
Params:
a = Pointer to the first block.
b = Pointer to the second block.
n = The number of bytes to compare.
Returns:
0 if they are equal, < 0 if a is less than b, and > 0 if a is greater than b.
*/
long memcmp(void* a, void* b, size_t n)
{
ubyte* str_a = cast(ubyte*)a;
ubyte* str_b = cast(ubyte*)b;
for(size_t i = 0; i < n; i++)
{
if(*str_a != *str_b)
return *str_a - *str_b;
str_a++;
str_b++;
}
return 0;
}
/**
This function sets a particular piece of memory to a particular value.
Params:
addr = The address of the piece of memory you wish to write.
val = The value you wish to write to memory.
numBytes = The number of bytes you would like to write to memory.
*/
void memset(void *addr, ubyte val, uint numBytes){
ubyte *data = cast(ubyte*) addr;
for(int i = 0; i < numBytes; i++){
data[i] = val;
}
}
/**
This function determines the size of a passed-in string.
Params:
s = A pointer to the beginning of a character array, declaring a string.
Returns: The size of the string in size_t format.
*/
size_t strlen(char* s)
{
size_t i = 0;
for( ; *s != 0; i++, s++){}
return i;
}
/**
This function takes in a character pointer and returns a character array, or a string.
Params:
s = A pointer to the character(s) you wish to translate to a string.
Returns: A character array (string) containing the information.
*/
char[] toString(char* s)
{
return s[0 .. strlen(s)];
}
/**
This function checks to see if a floating point number is a NaN.
Params:
e = The value / piece of information you would like to check for number status.
Returns:
0 if it isn't a NaN, non-zero if it is.
*/
int isnan(real e)
{
ushort* pe = cast(ushort *)&e;
ulong* ps = cast(ulong *)&e;
return (pe[4] & 0x7FFF) == 0x7FFF &&
*ps & 0x7FFFFFFFFFFFFFFF;
}