libc: Document the functions in string.h

This commit is contained in:
apio 2022-10-12 11:19:14 +02:00
parent 38e87d8f8f
commit 19ee20b6f5
2 changed files with 50 additions and 34 deletions

View File

@ -9,21 +9,37 @@ extern "C"
{ {
#endif #endif
void* memcpy(void*, const void*, size_t); /* Copies n bytes from src to dst. */
void* memset(void*, int, size_t); void* memcpy(void* dest, const void* src, size_t n);
void* memclr(void*, size_t);
size_t strlen(const char*); /* Sets n bytes of buf to c, cast to a character. */
void* memset(void* buf, int c, size_t n);
deprecated("strcpy is unsafe and should not be used; use strncpy instead") char* strcpy(char*, const char*); /* Clears n bytes of buf. */
char* strncpy(char*, const char*, size_t); void* memclr(void* buf, size_t n);
char* strchr(const char*, int); /* Returns the length of the string str. */
size_t strlen(const char* str);
deprecated("strcat is unsafe and should not be used; use strncat instead") char* strcat(char*, const char*); /* Copies the string src into dest. This function is unsafe, use strncpy instead. */
char* strncat(char*, const char*, size_t); deprecated("strcpy is unsafe and should not be used; use strncpy instead") char* strcpy(char* dest,
const char* src);
char* strerror(int); /* Copies at most max bytes from the string src into dest. */
char* strncpy(char* dest, const char* src, size_t max);
/* Returns a pointer to the first occurrence of the character c in str, or NULL if it is not found. */
char* strchr(const char* str, int c);
/* Concatenates the string src into dest. This function is unsafe, use strncat instead. */
deprecated("strcat is unsafe and should not be used; use strncat instead") char* strcat(char* dest,
const char* src);
/* Concatenates at most max bytes of the string src into dest. */
char* strncat(char* dest, const char* src, size_t max);
/* Returns the error string associated with the error number err. */
char* strerror(int err);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -10,18 +10,18 @@ extern "C"
return dest; return dest;
} }
void* memset(void* dest, int c, size_t n) void* memset(void* buf, int c, size_t n)
{ {
for (size_t i = 0; i < n; ++i) { *((char*)dest + i) = (char)c; } for (size_t i = 0; i < n; ++i) { *((char*)buf + i) = (char)c; }
return dest; return buf;
} }
size_t strlen(const char* s) size_t strlen(const char* str)
{ {
const char* i = s; const char* i = str;
for (; *i; ++i) for (; *i; ++i)
; ;
return (i - s); return (i - str);
} }
char* strcpy(char* dest, const char* src) char* strcpy(char* dest, const char* src)
@ -30,10 +30,10 @@ extern "C"
return dest; return dest;
} }
char* strncpy(char* dest, const char* src, size_t n) char* strncpy(char* dest, const char* src, size_t max)
{ {
size_t src_len = strlen(src) + 1; // NULL byte size_t src_len = strlen(src) + 1; // NULL byte
memcpy(dest, src, src_len > n ? n : src_len); memcpy(dest, src, src_len > max ? max : src_len);
return dest; return dest;
} }
@ -49,40 +49,40 @@ extern "C"
return dest; return dest;
} }
char* strncat(char* dest, const char* src, size_t n) char* strncat(char* dest, const char* src, size_t max)
{ {
size_t dest_len = strlen(dest); size_t dest_len = strlen(dest);
size_t i; size_t i;
for (i = 0; i < n && *(src + i); i++) *(char*)(dest + dest_len + i) = *(const char*)(src + i); for (i = 0; i < max && *(src + i); i++) *(char*)(dest + dest_len + i) = *(const char*)(src + i);
*(char*)(dest + dest_len + i) = '\0'; *(char*)(dest + dest_len + i) = '\0';
return dest; return dest;
} }
char* strchr(const char* str, int chr) char* strchr(const char* str, int c)
{ {
while (*str && *str != (char)chr) str++; while (*str && *str != (char)c) str++;
if (*str) return const_cast<char*>(str); if (*str) return const_cast<char*>(str);
return NULL; return NULL;
} }
void* memclr(void* start, size_t count) void* memclr(void* buf, size_t n)
{ {
// "i" is our counter of how many bytes we've cleared // "i" is our counter of how many bytes we've cleared
size_t i; size_t i;
// find out if "m_start" is aligned on a SSE_XMM_SIZE boundary // find out if "m_start" is aligned on a SSE_XMM_SIZE boundary
if ((size_t)start & (15)) if ((size_t)buf & (15))
{ {
i = 0; i = 0;
// we need to clear byte-by-byte until "m_start" is aligned on an SSE_XMM_SIZE boundary // 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) // ... and lets make sure we don't copy 'too' many bytes (i < m_count)
while (((size_t)start + i) & (15) && i < count) while (((size_t)buf + i) & (15) && i < n)
{ {
asm("stosb;" ::"D"((size_t)start + i), "a"(0)); asm("stosb;" ::"D"((size_t)buf + i), "a"(0));
i++; i++;
} }
} }
@ -93,31 +93,31 @@ extern "C"
} }
// clear 64-byte chunks of memory (4 16-byte operations) // clear 64-byte chunks of memory (4 16-byte operations)
for (; i + 64 <= count; i += 64) for (; i + 64 <= n; i += 64)
{ {
asm volatile(" pxor %%xmm0, %%xmm0; " // set XMM0 to 0 asm volatile(" pxor %%xmm0, %%xmm0; " // set XMM0 to 0
" movdqa %%xmm0, 0(%0); " // move 16 bytes from XMM0 to %0 + 0 " movdqa %%xmm0, 0(%0); " // move 16 bytes from XMM0 to %0 + 0
" movdqa %%xmm0, 16(%0); " " movdqa %%xmm0, 16(%0); "
" movdqa %%xmm0, 32(%0); " " movdqa %%xmm0, 32(%0); "
" movdqa %%xmm0, 48(%0); " ::"r"((size_t)start + i)); " movdqa %%xmm0, 48(%0); " ::"r"((size_t)buf + i));
} }
// copy the remaining bytes (if any) // copy the remaining bytes (if any)
asm(" rep stosb; " ::"a"((size_t)(0)), "D"(((size_t)start) + i), "c"(count - i)); 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" will contain the total amount of bytes that were actually transfered
i += count - i; i += n - i;
// we return "m_start" + the amount of bytes that were transfered // we return "m_start" + the amount of bytes that were transfered
return (void*)(((size_t)start) + i); return (void*)(((size_t)buf) + i);
} }
#pragma GCC push_options #pragma GCC push_options
#pragma GCC diagnostic ignored "-Wwrite-strings" #pragma GCC diagnostic ignored "-Wwrite-strings"
char* strerror(int errnum) char* strerror(int err)
{ {
switch (errnum) switch (err)
{ {
case EPERM: return "Operation not permitted"; case EPERM: return "Operation not permitted";
case EINVAL: return "Invalid argument"; case EINVAL: return "Invalid argument";
@ -128,7 +128,7 @@ extern "C"
case EMFILE: return "Too many open files"; case EMFILE: return "Too many open files";
case EISDIR: return "Is a directory"; case EISDIR: return "Is a directory";
case 0: return "Success"; case 0: return "Success";
default: return (char*)(unsigned long int)errnum; default: return (char*)(unsigned long int)err;
} }
} }