libc: add memchr(), strnlen(), strdup(), and rename memclr() to bzero()
This commit is contained in:
parent
523e88e5a9
commit
94a6336e4d
@ -15,12 +15,18 @@ extern "C"
|
|||||||
/* Sets n bytes of buf to c, cast to a character. */
|
/* Sets n bytes of buf to c, cast to a character. */
|
||||||
void* memset(void* buf, int c, size_t n);
|
void* memset(void* buf, int c, size_t n);
|
||||||
|
|
||||||
/* Clears n bytes of buf. */
|
/* Searches for the character c in n bytes of buf. */
|
||||||
void* memclr(void* buf, size_t n);
|
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. */
|
/* Returns the length of the string str. */
|
||||||
size_t strlen(const char* 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. */
|
/* 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,
|
__lc_deprecated("strcpy is unsafe and should not be used; use strncpy instead") char* strcpy(char* dest,
|
||||||
const char* src);
|
const char* src);
|
||||||
@ -41,6 +47,9 @@ extern "C"
|
|||||||
/* Returns the error string associated with the error number err. */
|
/* Returns the error string associated with the error number err. */
|
||||||
char* strerror(int err);
|
char* strerror(int err);
|
||||||
|
|
||||||
|
/* Clears n bytes of buf. */
|
||||||
|
void* bzero(void* buf, size_t n);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <luna.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
@ -16,6 +16,23 @@ extern "C"
|
|||||||
return buf;
|
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<char*>(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)
|
size_t strlen(const char* str)
|
||||||
{
|
{
|
||||||
const char* i = str;
|
const char* i = str;
|
||||||
@ -24,6 +41,12 @@ extern "C"
|
|||||||
return (i - str);
|
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)
|
char* strcpy(char* dest, const char* src)
|
||||||
{
|
{
|
||||||
memcpy(dest, src, strlen(src) + 1);
|
memcpy(dest, src, strlen(src) + 1);
|
||||||
@ -68,48 +91,9 @@ extern "C"
|
|||||||
return NULL;
|
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
|
return memset(buf, 0, n);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma GCC push_options
|
#pragma GCC push_options
|
||||||
|
Loading…
Reference in New Issue
Block a user