Chroma/chroma/video/print.c
2021-06-14 01:36:46 +01:00

202 lines
4.9 KiB
C

#include <kernel/chroma.h>
/************************
*** Team Kitty, 2020 ***
*** Chroma ***
***********************/
/* This file contains all of the String / Print related functions
* that are required by the core of the kernel.
*
* There will be a proper C++ std::string implementation in lainlib.
*
* This file also provides SerialPrintf.
*/
static size_t strlen(const char* String) {
size_t Len = 0;
while(String[Len] != '\0') {
Len++;
}
return Len;
}
static void NumToStr(char* Buffer, size_t Num, size_t Base) {
size_t Temp, i = 0, j = 0;
do {
Temp = Num % Base;
Buffer[i++] = (Temp < 10) ? (Temp + '0') : (Temp + 'a' - 10);
} while (Num /= Base);
Buffer[i--] = 0;
for(j = 0; j < i; j++, i--) {
Temp = Buffer[j];
Buffer[j] = Buffer[i];
Buffer[i] = Temp;
}
}
int SerialPrintf(const char* restrict Format, ...) {
va_list Parameters;
va_start(Parameters, Format);
int CharsWritten = 0;
size_t Base, Num;
char BufferStr[512] = {0};
while(*Format != '\0') {
size_t Limit = UINT64_MAX - CharsWritten;
if(*Format == '%') {
if(*(++Format) == '%')
Format++;
switch(*Format) {
case 'c':
Format++;
char c = (char) va_arg(Parameters, int);
WriteSerialString(&c, sizeof(c));
CharsWritten++;
break;
case 's':
Format++;
const char* Str = va_arg(Parameters, char*);
size_t Len = strlen(Str);
if(Limit < Len)
return -1;
WriteSerialString(Str, Len);
CharsWritten += Len;
break;
case 'd':
case 'u':
case 'p':
case 'x':
Num = va_arg(Parameters, size_t);
Base = 0;
if(*Format == 'd' || *Format == 'u') {
Base = 10; // Decimal & Unsigned are base 10
} else {
Base = 16; // Hex and Ptr are base 16
}
Format++;
NumToStr(BufferStr, Num, Base);
Len = strlen(BufferStr);
WriteSerialString(BufferStr, Len);
CharsWritten += Len;
break;
//case 'p':
//uint8_t Base = 16;
//size_t Dest = (uintptr_t) va_arg(Parameters, void*);
default:
WriteSerialString("%u", 2);
break;
}
} else {
WriteSerialChar(*Format);
Format++;
}
}
va_end(Parameters);
return CharsWritten;
}
int Printf(const char* restrict Format, ...) {
va_list Parameters;
va_start(Parameters, Format);
int CharsWritten = 0;
size_t Base, Num;
char BufferStr[512] = {0};
while(*Format != '\0') {
size_t Limit = UINT64_MAX - CharsWritten;
if(*Format == '%') {
if(*(++Format) == '%')
Format++;
switch(*Format) {
case 'c':
Format++;
char c = (char) va_arg(Parameters, int);
WriteString(&c);
CharsWritten++;
break;
case 's':
Format++;
const char* Str = va_arg(Parameters, char*);
size_t Len = strlen(Str);
if(Limit < Len)
return -1;
WriteString(Str);
CharsWritten += Len;
break;
case 'd':
case 'u':
case 'p':
case 'x':
Num = va_arg(Parameters, size_t);
Base = 0;
if(*Format == 'd' || *Format == 'u') {
Base = 10; // Decimal & Unsigned are base 10
} else {
Base = 16; // Hex and Ptr are base 16
}
Format++;
NumToStr(BufferStr, Num, Base);
Len = strlen(BufferStr);
WriteString(BufferStr);
CharsWritten += Len;
break;
//case 'p':
//uint8_t Base = 16;
//size_t Dest = (uintptr_t) va_arg(Parameters, void*);
default:
WriteString("%u");
break;
}
} else {
WriteChar(*Format);
Format++;
}
}
va_end(Parameters);
return CharsWritten;
}