diff options
Diffstat (limited to 'kernel/lib/string.cpp')
| -rw-r--r-- | kernel/lib/string.cpp | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/kernel/lib/string.cpp b/kernel/lib/string.cpp new file mode 100644 index 0000000..3bd60fa --- /dev/null +++ b/kernel/lib/string.cpp @@ -0,0 +1,78 @@ +// ============================================================================ +// lib/string.cpp - Freestanding memory and string operations +// +// These are required because we compile with -nostdlib. +// The compiler may generate implicit calls to memcpy/memset/memmove +// (e.g., for struct copies, array init), so these must exist with +// standard C linkage and standard names. +// ============================================================================ + +#include <stdint.h> +#include <stddef.h> + +extern "C" { + +void* memcpy(void* dest, const void* src, size_t n) { + auto* d = static_cast<uint8_t*>(dest); + auto* s = static_cast<const uint8_t*>(src); + for (size_t i = 0; i < n; i++) d[i] = s[i]; + return dest; +} + +void* memmove(void* dest, const void* src, size_t n) { + auto* d = static_cast<uint8_t*>(dest); + auto* s = static_cast<const uint8_t*>(src); + if (d < s) { + for (size_t i = 0; i < n; i++) d[i] = s[i]; + } else { + for (size_t i = n; i > 0; i--) d[i - 1] = s[i - 1]; + } + return dest; +} + +void* memset(void* dest, int val, size_t n) { + auto* d = static_cast<uint8_t*>(dest); + for (size_t i = 0; i < n; i++) d[i] = static_cast<uint8_t>(val); + return dest; +} + +int memcmp(const void* s1, const void* s2, size_t n) { + auto* a = static_cast<const uint8_t*>(s1); + auto* b = static_cast<const uint8_t*>(s2); + for (size_t i = 0; i < n; i++) { + // Cast to int before subtracting: uint8_t → int is safe, range [0, 255] + if (a[i] != b[i]) return static_cast<int>(a[i]) - static_cast<int>(b[i]); + } + return 0; +} + +size_t strlen(const char* s) { + size_t len = 0; + while (s[len]) len++; + return len; +} + +int strcmp(const char* s1, const char* s2) { + // Cast to unsigned before comparison — char may be signed, + // and unsigned subtraction gives the correct lexicographic ordering. + const auto* u1 = reinterpret_cast<const uint8_t*>(s1); + const auto* u2 = reinterpret_cast<const uint8_t*>(s2); + while (*u1 && *u1 == *u2) { ++u1; ++u2; } + return static_cast<int>(*u1) - static_cast<int>(*u2); +} + +char* strcpy(char* dest, const char* src) { + char* ret = dest; + while (*src) *dest++ = *src++; + *dest = '\0'; + return ret; +} + +char* strncpy(char* dest, const char* src, size_t n) { + size_t i = 0; + for (; i < n && src[i]; i++) dest[i] = src[i]; + for (; i < n; i++) dest[i] = '\0'; + return dest; +} + +} // extern "C" |
