Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion include/uv_string.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
char* uvStrchr(const char* s, const char c);
u32 uvStrlen(const char* s);
int uvStrcmp(const char* s1, const char* s2);
void strFormatFloat(f32 number, s32 *bufPosPtr, char* strBuf);
void strFormatInt(s32 number, u16 base, s32 *bufPosPtr, char* strBuf, s32 padCount, s32 leftJustify, s32 hasZeroPadding);
char strDigitToChar(u16 digit);
void uvSprintf(char* dest, const char* fmt, ...);
int uvAtoi(const char*);
int uvAtoi(const char* s);

#endif // UV_STRING_H
222 changes: 204 additions & 18 deletions src/kernel/string.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,6 @@
#include <PR/ultratypes.h>
#include <uv_string.h>

// forward declarations
void strFormatFloat(f32, s32*, char*, s32);
void strFormatInt(s32, s32 base, s32*, char*, s32, s32, s32);

char* uvStrchr(const char* s, const char c) {
while (*s != '\0' && c != *s) {
s++;
Expand All @@ -17,17 +13,194 @@ char* uvStrchr(const char* s, const char c) {
return NULL;
}

#pragma GLOBAL_ASM("asm/nonmatchings/kernel/string/uvStrlen.s")
u32 uvStrlen(const char* s) {
s32 len;

len = 0;
while (*s++ != 0) {
len++;
}
return len;
}

int uvStrcmp(const char* s1, const char* s2) {
s32 len1;
s32 len2;
s32 i;

len1 = uvStrlen(s1);
len2 = uvStrlen(s2);

#pragma GLOBAL_ASM("asm/nonmatchings/kernel/string/uvStrcmp.s")
if (len1 < len2) {
return -1;
}
if (len2 < len1) {
return 1;
}

for (i = 0; i < len1; i++) {
if (*s1 < *s2) {
return -1;
}
if (*s1 > *s2) {
return 1;
}

#pragma GLOBAL_ASM("asm/nonmatchings/kernel/string/strFormatInt.s")
s1++;
s2++;
}

#pragma GLOBAL_ASM("asm/nonmatchings/kernel/string/strFormatFloat.s")
return 0;
}

#pragma GLOBAL_ASM("asm/nonmatchings/kernel/string/strDigitToChar.s")
void strFormatInt(s32 number, u16 base, s32* bufPosPtr, char* strBuf, s32 padCount, s32 leftJustify, s32 hasZeroPadding) {
u16 digit;
u16 numDigits;
s32 outputLength;
s32 bufPos;
u16 isNegative;
s32 i;
s32 digitsRemaining;
s32 inputLengthRemaining;
s32 outputLengthRemaining;

#pragma GLOBAL_ASM("asm/nonmatchings/kernel/string/strCharToDigit.s")
bufPos = *bufPosPtr;
if (number < 0) {
isNegative = TRUE;
number = -number;
} else {
isNegative = FALSE;
}
numDigits = 0;
i = 1;
if (number != 0) {
while (number >= i) {
numDigits++;
i *= base;
}
} else {
numDigits = 1;
}

if (padCount > 0) {
outputLength = padCount;
} else {
outputLength = numDigits + isNegative;
}
bufPos += outputLength;
bufPos--;
outputLengthRemaining = outputLength;
digitsRemaining = numDigits;
inputLengthRemaining = numDigits + isNegative;
if (leftJustify) {
for (i = 0; i < outputLength; i++) {
if (inputLengthRemaining < outputLengthRemaining) {
strBuf[bufPos--] = ' ';
outputLengthRemaining--;
} else if (digitsRemaining > 0) {
digit = number % base;
strBuf[bufPos--] = strDigitToChar(digit);
number = (number - digit) / base;
digitsRemaining--;
outputLengthRemaining--;
inputLengthRemaining--;
} else if (inputLengthRemaining == 1) {
strBuf[bufPos--] = ' ';
}
}
} else {
for (i = 0; i < outputLength; i++) {
if (digitsRemaining > 0) {
digit = number % base;
strBuf[bufPos--] = strDigitToChar(digit);
number = (number - digit) / base;
} else {
if (hasZeroPadding) {
if ((i == outputLength - 1) && isNegative) {
strBuf[bufPos--] = '-';
} else {
strBuf[bufPos--] = '0';
}
} else {
if ((digitsRemaining == 0) && isNegative) {
strBuf[bufPos--] = '-';
} else {
strBuf[bufPos--] = ' ';
}
}
}
digitsRemaining--;
}
}
bufPos += outputLength;
bufPos++;
*bufPosPtr = bufPos;
}

void strFormatFloat(f32 number, s32* bufPosPtr, char* strBuf) {
f32 decimalPart;
u16 digit;
s32 i;
s32 integerPart;
u16 isNegative;
u16 numDigits;
s32 bufPos;

bufPos = *bufPosPtr;
if (number < 0.0f) {
isNegative = TRUE;
number = -number;
} else {
isNegative = FALSE;
}
integerPart = (s32)number;
numDigits = 0;
i = 1;
if (integerPart != 0) {
while (integerPart >= i) {
numDigits++;
i *= 10;
}
} else {
numDigits = 1;
}
bufPos += numDigits + isNegative;
strBuf[bufPos++] = '.';
decimalPart = number - integerPart;

for (i = 0; i < 2; i++) {
decimalPart *= 10.0f;
digit = (s32)decimalPart;
decimalPart -= digit;
strBuf[bufPos++] = strDigitToChar(digit);
}
bufPos -= 4;

for (i = 0; i < numDigits; i++) {
digit = integerPart % 10;
strBuf[bufPos--] = strDigitToChar(digit);
integerPart = (integerPart - digit) / 10;
}
if (isNegative) {
strBuf[bufPos--] = '-';
}
bufPos += numDigits + isNegative + 4;
*bufPosPtr = bufPos;
}

char strDigitToChar(u16 digit) {
if (digit < 10) {
return '0' + digit;
}
return ' ';
}

s32 strCharToDigit(char digitChar) {
if ((digitChar >= '0') && (digitChar <= '9')) {
return digitChar - '0';
}
return 0;
}

void uvSprintf(char* dest, const char* fmt, ...) {
s32 srcBufPos;
Expand All @@ -37,7 +210,7 @@ void uvSprintf(char* dest, const char* fmt, ...) {
char* argStr;
s32 arg;
s32 padCount;
int hasPadding;
int hasZeroPadding;
int leftJustify;
u8 c;
int parseSpecifier;
Expand All @@ -53,7 +226,7 @@ void uvSprintf(char* dest, const char* fmt, ...) {
if (c == '%') {
padCount = -1;
leftJustify = FALSE;
hasPadding = FALSE;
hasZeroPadding = FALSE;
parseSpecifier = TRUE;
} else {
dest[destBufPos] = c;
Expand All @@ -71,7 +244,7 @@ void uvSprintf(char* dest, const char* fmt, ...) {
if (c == '0') {
srcBufPos++;
c = fmt[srcBufPos];
hasPadding = TRUE;
hasZeroPadding = TRUE;
}
if (c == '\0') {
break;
Expand Down Expand Up @@ -107,18 +280,18 @@ void uvSprintf(char* dest, const char* fmt, ...) {
}
if (c == 'x') {
arg = va_arg(args, s32);
strFormatInt(arg, 16, &destBufPos, dest, padCount, leftJustify, hasPadding);
strFormatInt(arg, 16, &destBufPos, dest, padCount, leftJustify, hasZeroPadding);
parseSpecifier = FALSE;
} else if (c == 'd') {
arg = va_arg(args, s32);
strFormatInt(arg, 10, &destBufPos, dest, padCount, leftJustify, hasPadding);
strFormatInt(arg, 10, &destBufPos, dest, padCount, leftJustify, hasZeroPadding);
parseSpecifier = FALSE;
} else if (c == 'b') {
arg = va_arg(args, s32);
strFormatInt(arg, 2, &destBufPos, dest, padCount, leftJustify, hasPadding);
strFormatInt(arg, 2, &destBufPos, dest, padCount, leftJustify, hasZeroPadding);
parseSpecifier = FALSE;
} else if (c == 'f') {
strFormatFloat(va_arg(args, f64), &destBufPos, dest, c);
strFormatFloat(va_arg(args, f64), &destBufPos, dest);
parseSpecifier = FALSE;
} else if (c == 's') {
argStr = arg = va_arg(args, char*);
Expand All @@ -136,4 +309,17 @@ void uvSprintf(char* dest, const char* fmt, ...) {
va_end(args);
}

#pragma GLOBAL_ASM("asm/nonmatchings/kernel/string/uvAtoi.s")
int uvAtoi(const char* s) {
s32 len;
s32 i;
s32 number;

len = uvStrlen(s);
number = 0;

for (i = 0; i < len; i++) {
number *= 10;
number += strCharToDigit(s[i]);
}
return number;
}