undar-lang/src/str.c

149 lines
3.2 KiB
C

#include "str.h"
i32 strcopy(char *to, const char *from, u32 length) {
u32 i;
if (to == nil || from == nil) return -1;
if (length == 0) {return 0;}
for (i = 0; i < length - 1 && from[i] != '\0'; i++) {
to[i] = from[i];
}
to[i] = '\0';
return 0;
}
bool streq(const char *s1, const char *s2) {
if (s1 == nil && s2 == nil) return true;
if (s1 == nil || s2 == nil) return false;
while (*s1 && *s2) {
if (*s1 != *s2) return false;
s1++;
s2++;
}
return (*s1 == '\0' && *s2 == '\0');
}
u32 strlen(const char *str) {
u32 i;
if (str == nil) {return 0;}
for (i = 0; str[i] != '\0'; i++) {
; /* twiddle thumbs, 'i' is doing all the work*/
}
return i;
}
u32 strnlen(const char *str, u32 max_len) {
u32 i;
if (str == nil) {return 0;}
for (i = 0; i < max_len && str[i] != '\0'; i++) {
; /* twiddle thumbs, 'i' is doing all the work*/
}
return i;
}
/* Static digit lookup table (0-9) */
const char digits[10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
/* Writes decimal digits of 'value' backwards into 'buf_end' (inclusive),
stopping at 'buf_start'. Returns pointer to first written digit. */
char *write_digits_backwards(u32 value, char *buf_end, char *buf_start) {
char *p = buf_end;
if (value == 0) {
*--p = '0';
} else {
u32 num = value;
while (num && p > buf_start) {
*--p = digits[num % 10];
num /= 10;
}
}
return p;
}
void uint_to_string(u32 value, char *buffer) {
char temp[16];
char *start;
char *end = temp + sizeof(temp) - 1;
*end = '\0';
start = write_digits_backwards(value, end, temp);
strcopy(buffer, start, end - start + 1); /* +1 for null terminator */
}
void int_to_string(i32 value, char *buffer) {
char temp[17]; /* Extra space for '-' */
i32 negative = 0;
u32 abs_value;
char *end = temp + sizeof(temp) - 1;
*end = '\0';
if (value == (-2147483647 - 1)) { /* INT32_MIN */
strcopy(buffer, "-2147483648", 12);
return;
}
if (value == 0) {
*--end = '0';
} else {
if (value < 0) {
negative = 1;
abs_value = (u32)(-value);
} else {
abs_value = (u32)value;
}
end = write_digits_backwards(abs_value, end, temp);
if (negative) {
*--end = '-';
}
}
strcopy(buffer, end, temp + sizeof(temp) - end);
}
void fixed_to_string(i32 value, char *buffer) {
char temp[32];
i32 negative;
u32 int_part;
u32 frac_part, frac_digits;
char *end = temp + sizeof(temp) - 1;
*end = '\0';
negative = 0;
if (value < 0) {
negative = 1;
value = -value;
}
int_part = AS_UINT(value >> 16);
frac_part = AS_UINT(value & 0xFFFF);
/* Convert fractional part to 5 decimal digits */
frac_digits = (frac_part * 100000U) / 65536U;
/* Trim trailing zeros */
while (frac_digits > 0 && frac_digits % 10 == 0) {
frac_digits /= 10;
}
if (frac_digits > 0) {
end = write_digits_backwards(frac_digits, end, temp);
*--end = '.';
}
if (int_part == 0 && frac_digits == 0) {
*--end = '0';
} else {
end = write_digits_backwards(int_part, end, temp);
}
if (negative) {
*--end = '-';
}
strcopy(buffer, end, temp + sizeof(temp) - end);
}