257 lines
6.1 KiB
C
257 lines
6.1 KiB
C
#include "libc.h"
|
|
|
|
void memcopy(u8 *dest, const u8 *src, u32 n) {
|
|
size_t i;
|
|
size_t words;
|
|
size_t bytes;
|
|
size_t unroll;
|
|
size_t remainder;
|
|
u32 *d32;
|
|
const u32 *s32;
|
|
u8 *d8;
|
|
const u8 *s8;
|
|
|
|
/* Fast path for small copies (common case) */
|
|
if (n <= 8) {
|
|
for (i = 0; i < n; i++) {
|
|
dest[i] = src[i];
|
|
}
|
|
return;
|
|
}
|
|
|
|
/* Check for word alignment (assuming 32-bit words) */
|
|
if ((((size_t)dest) & 0x3) == 0 && (((size_t)src) & 0x3) == 0) {
|
|
/* Both pointers are 4-byte aligned - copy by words */
|
|
d32 = (u32 *)dest;
|
|
s32 = (const u32 *)src;
|
|
words = n / 4;
|
|
bytes = n % 4;
|
|
|
|
/* Loop unrolling - 4x unroll for better performance */
|
|
unroll = words / 4;
|
|
remainder = words % 4;
|
|
|
|
for (i = 0; i < unroll; i++) {
|
|
d32[0] = s32[0];
|
|
d32[1] = s32[1];
|
|
d32[2] = s32[2];
|
|
d32[3] = s32[3];
|
|
d32 += 4;
|
|
s32 += 4;
|
|
}
|
|
|
|
/* Handle remaining words */
|
|
for (i = 0; i < remainder; i++) {
|
|
*d32++ = *s32++;
|
|
}
|
|
|
|
/* Handle trailing bytes */
|
|
d8 = (u8 *)d32;
|
|
s8 = (const u8 *)s32;
|
|
for (i = 0; i < bytes; i++) {
|
|
d8[i] = s8[i];
|
|
}
|
|
} else {
|
|
/* Unaligned copy - byte by byte but with loop unrolling */
|
|
unroll = n / 4;
|
|
remainder = n % 4;
|
|
|
|
for (i = 0; i < unroll; i++) {
|
|
dest[0] = src[0];
|
|
dest[1] = src[1];
|
|
dest[2] = src[2];
|
|
dest[3] = src[3];
|
|
dest += 4;
|
|
src += 4;
|
|
}
|
|
|
|
for (i = 0; i < remainder; i++) {
|
|
dest[i] = src[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
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');
|
|
}
|
|
|
|
bool strleq(const char *s1, const char *s2, u32 length) {
|
|
u32 i;
|
|
if (s1 == nil && s2 == nil) return true;
|
|
if (s1 == nil || s2 == nil) return false;
|
|
|
|
i = 0;
|
|
while (i < length && *s1 && *s2) {
|
|
if (*s1 != *s2) return false;
|
|
s1++;
|
|
s2++;
|
|
i++;
|
|
}
|
|
if (i == length) return true;
|
|
return (*s1 == '\0' && *s2 == '\0');
|
|
}
|
|
|
|
u32 strlength(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 strnlength(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 nat_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, original_frac_digits;
|
|
char *end = temp + sizeof(temp) - 1;
|
|
char *frac_start;
|
|
*end = '\0';
|
|
|
|
negative = 0;
|
|
if (value < 0) {
|
|
negative = 1;
|
|
value = -value;
|
|
}
|
|
|
|
int_part = AS_NAT(value >> 16);
|
|
frac_part = AS_NAT(value & 0xFFFF);
|
|
|
|
/* Convert fractional part to 5 decimal digits */
|
|
original_frac_digits = (frac_part * 100000U) / 65536U;
|
|
frac_digits = original_frac_digits;
|
|
|
|
if (frac_digits > 0) {
|
|
/* Write fractional digits backwards */
|
|
frac_start = write_digits_backwards(frac_digits, end, temp);
|
|
|
|
/* Remove trailing zeros by moving the start pointer */
|
|
while (*(end - 1) == '0' && end > frac_start) {
|
|
end--;
|
|
}
|
|
|
|
/* If all fractional digits were zeros after removing trailing zeros,
|
|
we need to add back one zero to represent the .0 */
|
|
if (end == frac_start) {
|
|
*--end = '0';
|
|
}
|
|
|
|
/* Add decimal point */
|
|
*--end = '.';
|
|
} else if (frac_part > 0) {
|
|
/* Handle case where original_frac_digits was rounded to 0 but frac_part was not 0 */
|
|
/* This means we have a very small fractional part that should be represented as .0 */
|
|
*--end = '0';
|
|
*--end = '.';
|
|
} else if (frac_part == 0) {
|
|
/* No fractional part - just add .0 if we have an integer part */
|
|
if (int_part != 0) {
|
|
*--end = '0';
|
|
*--end = '.';
|
|
}
|
|
}
|
|
|
|
if (int_part == 0 && frac_digits == 0 && frac_part == 0) {
|
|
*--end = '0';
|
|
} else {
|
|
end = write_digits_backwards(int_part, end, temp);
|
|
}
|
|
|
|
if (negative) {
|
|
*--end = '-';
|
|
}
|
|
|
|
strcopy(buffer, end, temp + sizeof(temp) - end);
|
|
}
|