diff --git a/libs/libc/include/string.h b/libs/libc/include/string.h index f8e94c17..af9c617e 100644 --- a/libs/libc/include/string.h +++ b/libs/libc/include/string.h @@ -15,12 +15,18 @@ extern "C" /* Sets n bytes of buf to c, cast to a character. */ void* memset(void* buf, int c, size_t n); - /* Clears n bytes of buf. */ - void* memclr(void* buf, size_t n); + /* Searches for the character c in n bytes of buf. */ + void* memchr(const void* buf, int c, size_t n); + + /* Returns a heap-allocated copy of the string str. Should be freed when it is not used anymore. */ + char* strdup(const char* str); /* Returns the length of the string str. */ size_t strlen(const char* str); + /* Returns the length of the string str, while examining at most max bytes of str. */ + size_t strnlen(const char* str, size_t max); + /* Copies the string src into dest. This function is unsafe, use strncpy instead. */ __lc_deprecated("strcpy is unsafe and should not be used; use strncpy instead") char* strcpy(char* dest, const char* src); @@ -41,6 +47,9 @@ extern "C" /* Returns the error string associated with the error number err. */ char* strerror(int err); + /* Clears n bytes of buf. */ + void* bzero(void* buf, size_t n); + #ifdef __cplusplus } #endif diff --git a/libs/libc/src/string.cpp b/libs/libc/src/string.cpp index 93b1ae46..034c6d24 100644 --- a/libs/libc/src/string.cpp +++ b/libs/libc/src/string.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include extern "C" @@ -16,6 +16,23 @@ extern "C" return buf; } + void* memchr(const void* buf, int c, size_t n) + { + const char* s = (const char*)buf; + for (; n && *s != (char)c; s++, n--) + ; + if (n) return (void*)(const_cast(s)); + return NULL; + } + + char* strdup(const char* str) + { + size_t len = strlen(str); + char* dest = (char*)malloc(len + 1); + if (!dest) return dest; + return (char*)memcpy(dest, str, len + 1); + } + size_t strlen(const char* str) { const char* i = str; @@ -24,6 +41,12 @@ extern "C" return (i - str); } + size_t strnlen(const char* str, size_t max) + { + char* p = (char*)memchr(str, 0, max); + return p ? p - str : max; + } + char* strcpy(char* dest, const char* src) { memcpy(dest, src, strlen(src) + 1); @@ -68,48 +91,9 @@ extern "C" return NULL; } - void* memclr(void* buf, size_t n) + void* bzero(void* buf, size_t n) { - // "i" is our counter of how many bytes we've cleared - size_t i; - - // find out if "m_start" is aligned on a SSE_XMM_SIZE boundary - if ((size_t)buf & (15)) - { - i = 0; - - // we need to clear byte-by-byte until "m_start" is aligned on an SSE_XMM_SIZE boundary - // ... and lets make sure we don't copy 'too' many bytes (i < m_count) - while (((size_t)buf + i) & (15) && i < n) - { - asm("stosb;" ::"D"((size_t)buf + i), "a"(0)); - i++; - } - } - else - { - // if "m_start" was aligned, set our count to 0 - i = 0; - } - - // clear 64-byte chunks of memory (4 16-byte operations) - for (; i + 64 <= n; i += 64) - { - asm volatile(" pxor %%xmm0, %%xmm0; " // set XMM0 to 0 - " movdqa %%xmm0, 0(%0); " // move 16 bytes from XMM0 to %0 + 0 - " movdqa %%xmm0, 16(%0); " - " movdqa %%xmm0, 32(%0); " - " movdqa %%xmm0, 48(%0); " ::"r"((size_t)buf + i)); - } - - // copy the remaining bytes (if any) - asm(" rep stosb; " ::"a"((size_t)(0)), "D"(((size_t)buf) + i), "c"(n - i)); - - // "i" will contain the total amount of bytes that were actually transfered - i += n - i; - - // we return "m_start" + the amount of bytes that were transfered - return (void*)(((size_t)buf) + i); + return memset(buf, 0, n); } #pragma GCC push_options