mirror of
https://github.com/EnderIce2/Fennix.git
synced 2025-05-28 15:34:31 +00:00
feat(userspace/libc): implement all <string.h> functions
Implement all string.h functions except some which require locale which is not implemented yet Signed-off-by: EnderIce2 <enderice2@protonmail.com>
This commit is contained in:
parent
6dfefc90c4
commit
0f9a1915d1
@ -26,43 +26,43 @@ extern "C"
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
|
|
||||||
void *memccpy(void *restrict, const void *restrict, int, size_t);
|
void *memccpy(void *restrict s1, const void *restrict s2, int c, size_t n);
|
||||||
void *memchr(const void *, int, size_t);
|
void *memchr(const void *s, int c, size_t n);
|
||||||
int memcmp(const void *, const void *, size_t);
|
int memcmp(const void *s1, const void *s2, size_t n);
|
||||||
void *memcpy(void *restrict s1, const void *restrict s2, size_t n);
|
void *memcpy(void *restrict s1, const void *restrict s2, size_t n);
|
||||||
void *memmem(const void *, size_t, const void *, size_t);
|
void *memmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen);
|
||||||
void *memmove(void *, const void *, size_t);
|
void *memmove(void *s1, const void *s2, size_t n);
|
||||||
void *memset(void *, int, size_t);
|
void *memset(void *s, int c, size_t n);
|
||||||
char *stpcpy(char *restrict, const char *restrict);
|
char *stpcpy(char *restrict s1, const char *restrict s2);
|
||||||
char *stpncpy(char *restrict, const char *restrict, size_t);
|
char *stpncpy(char *restrict s1, const char *restrict s2, size_t n);
|
||||||
char *strcat(char *restrict, const char *restrict);
|
char *strcat(char *restrict s1, const char *restrict s2);
|
||||||
char *strchr(const char *s, int c);
|
char *strchr(const char *s, int c);
|
||||||
int strcmp(const char *s1, const char *s2);
|
int strcmp(const char *s1, const char *s2);
|
||||||
int strcoll(const char *s1, const char *s2);
|
int strcoll(const char *s1, const char *s2);
|
||||||
int strcoll_l(const char *, const char *, locale_t);
|
int strcoll_l(const char *s1, const char *s2, locale_t locale);
|
||||||
char *strcpy(char *restrict s1, const char *restrict s2);
|
char *strcpy(char *restrict s1, const char *restrict s2);
|
||||||
size_t strcspn(const char *s1, const char *s2);
|
size_t strcspn(const char *s1, const char *s2);
|
||||||
char *strdup(const char *);
|
char *strdup(const char *s);
|
||||||
char *strerror(int);
|
char *strerror(int errnum);
|
||||||
char *strerror_l(int, locale_t);
|
char *strerror_l(int errnum, locale_t locale);
|
||||||
int strerror_r(int, char *, size_t);
|
int strerror_r(int errnum, char *strerrbuf, size_t buflen);
|
||||||
size_t strlcat(char *restrict, const char *restrict, size_t);
|
size_t strlcat(char *restrict dst, const char *restrict src, size_t dstsize);
|
||||||
size_t strlcpy(char *restrict, const char *restrict, size_t);
|
size_t strlcpy(char *restrict dst, const char *restrict src, size_t dstsize);
|
||||||
size_t strlen(const char *s);
|
size_t strlen(const char *s);
|
||||||
char *strncat(char *restrict, const char *restrict, size_t);
|
char *strncat(char *restrict s1, const char *restrict s2, size_t n);
|
||||||
int strncmp(const char *s1, const char *s2, size_t n);
|
int strncmp(const char *s1, const char *s2, size_t n);
|
||||||
char *strncpy(char *restrict s1, const char *restrict s2, size_t n);
|
char *strncpy(char *restrict s1, const char *restrict s2, size_t n);
|
||||||
char *strndup(const char *, size_t);
|
char *strndup(const char *s, size_t size);
|
||||||
size_t strnlen(const char *, size_t);
|
size_t strnlen(const char *s, size_t maxlen);
|
||||||
char *strpbrk(const char *s1, const char *s2);
|
char *strpbrk(const char *s1, const char *s2);
|
||||||
char *strrchr(const char *, int);
|
char *strrchr(const char *s, int c);
|
||||||
char *strsignal(int signum);
|
char *strsignal(int signum);
|
||||||
size_t strspn(const char *s1, const char *s2);
|
size_t strspn(const char *s1, const char *s2);
|
||||||
char *strstr(const char *, const char *);
|
char *strstr(const char *s1, const char *s2);
|
||||||
char *strtok(char *restrict s, const char *restrict sep);
|
char *strtok(char *restrict s, const char *restrict sep);
|
||||||
char *strtok_r(char *restrict s, const char *restrict sep, char **restrict state);
|
char *strtok_r(char *restrict s, const char *restrict sep, char **restrict state);
|
||||||
size_t strxfrm(char *restrict, const char *restrict, size_t);
|
size_t strxfrm(char *restrict s1, const char *restrict s2, size_t n);
|
||||||
size_t strxfrm_l(char *restrict, const char *restrict, size_t, locale_t);
|
size_t strxfrm_l(char *restrict s1, const char *restrict s2, size_t n, locale_t locale);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -18,10 +18,53 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <fennix/syscalls.h>
|
#include <fennix/syscalls.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
export void *memccpy(void *restrict, const void *restrict, int, size_t);
|
export void *memccpy(void *restrict s1, const void *restrict s2, int c, size_t n)
|
||||||
export void *memchr(const void *, int, size_t);
|
{
|
||||||
export int memcmp(const void *, const void *, size_t);
|
unsigned char *dest = (unsigned char *)s1;
|
||||||
|
const unsigned char *src = (const unsigned char *)s2;
|
||||||
|
unsigned char uc = (unsigned char)c;
|
||||||
|
|
||||||
|
while (n--)
|
||||||
|
{
|
||||||
|
*dest = *src;
|
||||||
|
if (*src == uc)
|
||||||
|
return (void *)(dest + 1);
|
||||||
|
dest++;
|
||||||
|
src++;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
export void *memchr(const void *s, int c, size_t n)
|
||||||
|
{
|
||||||
|
const unsigned char *src = (const unsigned char *)s;
|
||||||
|
unsigned char uc = (unsigned char)c;
|
||||||
|
|
||||||
|
while (n--)
|
||||||
|
{
|
||||||
|
if (*src == uc)
|
||||||
|
return (void *)src;
|
||||||
|
src++;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
export int memcmp(const void *s1, const void *s2, size_t n)
|
||||||
|
{
|
||||||
|
const unsigned char *p1 = (const unsigned char *)s1;
|
||||||
|
const unsigned char *p2 = (const unsigned char *)s2;
|
||||||
|
|
||||||
|
while (n--)
|
||||||
|
{
|
||||||
|
if (*p1 != *p2)
|
||||||
|
return *p1 - *p2;
|
||||||
|
p1++;
|
||||||
|
p2++;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
export void *memcpy(void *restrict s1, const void *restrict s2, size_t n)
|
export void *memcpy(void *restrict s1, const void *restrict s2, size_t n)
|
||||||
{
|
{
|
||||||
@ -41,12 +84,87 @@ export void *memcpy(void *restrict s1, const void *restrict s2, size_t n)
|
|||||||
return s1;
|
return s1;
|
||||||
}
|
}
|
||||||
|
|
||||||
export void *memmem(const void *, size_t, const void *, size_t);
|
export void *memmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen)
|
||||||
export void *memmove(void *, const void *, size_t);
|
{
|
||||||
export void *memset(void *, int, size_t);
|
const unsigned char *h = (const unsigned char *)haystack;
|
||||||
export char *stpcpy(char *restrict, const char *restrict);
|
const unsigned char *n = (const unsigned char *)needle;
|
||||||
export char *stpncpy(char *restrict, const char *restrict, size_t);
|
|
||||||
export char *strcat(char *restrict, const char *restrict);
|
if (needlelen == 0)
|
||||||
|
return (void *)haystack;
|
||||||
|
|
||||||
|
if (haystacklen < needlelen)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (size_t i = 0; i <= haystacklen - needlelen; i++)
|
||||||
|
{
|
||||||
|
if (memcmp(h + i, n, needlelen) == 0)
|
||||||
|
return (void *)(h + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
export void *memmove(void *s1, const void *s2, size_t n)
|
||||||
|
{
|
||||||
|
unsigned char *dest = (unsigned char *)s1;
|
||||||
|
const unsigned char *src = (const unsigned char *)s2;
|
||||||
|
|
||||||
|
if (dest < src)
|
||||||
|
{
|
||||||
|
while (n--)
|
||||||
|
*dest++ = *src++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dest += n;
|
||||||
|
src += n;
|
||||||
|
while (n--)
|
||||||
|
*--dest = *--src;
|
||||||
|
}
|
||||||
|
|
||||||
|
return s1;
|
||||||
|
}
|
||||||
|
|
||||||
|
export void *memset(void *s, int c, size_t n)
|
||||||
|
{
|
||||||
|
unsigned char *p = (unsigned char *)s;
|
||||||
|
while (n--)
|
||||||
|
*p++ = (unsigned char)c;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
export char *stpcpy(char *restrict s1, const char *restrict s2)
|
||||||
|
{
|
||||||
|
while ((*s1 = *s2) != '\0')
|
||||||
|
{
|
||||||
|
s1++;
|
||||||
|
s2++;
|
||||||
|
}
|
||||||
|
return s1;
|
||||||
|
}
|
||||||
|
|
||||||
|
export char *stpncpy(char *restrict s1, const char *restrict s2, size_t n)
|
||||||
|
{
|
||||||
|
char *dest = s1;
|
||||||
|
while (n && (*dest++ = *s2++))
|
||||||
|
n--;
|
||||||
|
|
||||||
|
if (n)
|
||||||
|
while (--n)
|
||||||
|
*dest++ = '\0';
|
||||||
|
|
||||||
|
return dest - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
export char *strcat(char *restrict s1, const char *restrict s2)
|
||||||
|
{
|
||||||
|
char *dest = s1;
|
||||||
|
while (*dest)
|
||||||
|
dest++;
|
||||||
|
while ((*dest++ = *s2++))
|
||||||
|
;
|
||||||
|
return s1;
|
||||||
|
}
|
||||||
|
|
||||||
export char *strchr(const char *s, int c)
|
export char *strchr(const char *s, int c)
|
||||||
{
|
{
|
||||||
@ -83,7 +201,7 @@ export int strcoll(const char *s1, const char *s2)
|
|||||||
return *(unsigned char *)s1 - *(unsigned char *)s2;
|
return *(unsigned char *)s1 - *(unsigned char *)s2;
|
||||||
}
|
}
|
||||||
|
|
||||||
export int strcoll_l(const char *, const char *, locale_t);
|
export int strcoll_l(const char *s1, const char *s2, locale_t locale);
|
||||||
|
|
||||||
export char *strcpy(char *restrict s1, const char *restrict s2)
|
export char *strcpy(char *restrict s1, const char *restrict s2)
|
||||||
{
|
{
|
||||||
@ -111,12 +229,236 @@ export size_t strcspn(const char *s1, const char *s2)
|
|||||||
return p - 1 - s1;
|
return p - 1 - s1;
|
||||||
}
|
}
|
||||||
|
|
||||||
export char *strdup(const char *);
|
export char *strdup(const char *s)
|
||||||
export char *strerror(int);
|
{
|
||||||
export char *strerror_l(int, locale_t);
|
size_t len = strlen(s) + 1;
|
||||||
export int strerror_r(int, char *, size_t);
|
char *new_str = (char *)malloc(len);
|
||||||
export size_t strlcat(char *restrict, const char *restrict, size_t);
|
if (!new_str)
|
||||||
export size_t strlcpy(char *restrict, const char *restrict, size_t);
|
return NULL;
|
||||||
|
memcpy(new_str, s, len);
|
||||||
|
return new_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
export char *strerror(int errnum)
|
||||||
|
{
|
||||||
|
static char unknown_error[32];
|
||||||
|
switch (errnum)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
return "No error";
|
||||||
|
case E2BIG:
|
||||||
|
return "Argument list too long";
|
||||||
|
case EACCES:
|
||||||
|
return "Permission denied";
|
||||||
|
case EADDRINUSE:
|
||||||
|
return "Address in use";
|
||||||
|
case EADDRNOTAVAIL:
|
||||||
|
return "Address not available";
|
||||||
|
case EAFNOSUPPORT:
|
||||||
|
return "Address family not supported";
|
||||||
|
case EAGAIN:
|
||||||
|
return "Resource temporarily unavailable";
|
||||||
|
case EALREADY:
|
||||||
|
return "Connection already in progress";
|
||||||
|
case EBADF:
|
||||||
|
return "Bad file descriptor";
|
||||||
|
case EBADMSG:
|
||||||
|
return "Bad message";
|
||||||
|
case EBUSY:
|
||||||
|
return "Resource busy";
|
||||||
|
case ECANCELED:
|
||||||
|
return "Operation canceled";
|
||||||
|
case ECHILD:
|
||||||
|
return "No child process";
|
||||||
|
case ECONNABORTED:
|
||||||
|
return "Connection aborted";
|
||||||
|
case ECONNREFUSED:
|
||||||
|
return "Connection refused";
|
||||||
|
case ECONNRESET:
|
||||||
|
return "Connection reset";
|
||||||
|
case EDEADLK:
|
||||||
|
return "Resource deadlock would occur";
|
||||||
|
case EDESTADDRREQ:
|
||||||
|
return "Destination address required";
|
||||||
|
case EDOM:
|
||||||
|
return "Domain error";
|
||||||
|
case EEXIST:
|
||||||
|
return "File exists";
|
||||||
|
case EFAULT:
|
||||||
|
return "Bad address";
|
||||||
|
case EFBIG:
|
||||||
|
return "File too large";
|
||||||
|
case EHOSTUNREACH:
|
||||||
|
return "Host is unreachable";
|
||||||
|
case EIDRM:
|
||||||
|
return "Identifier removed";
|
||||||
|
case EILSEQ:
|
||||||
|
return "Illegal byte sequence";
|
||||||
|
case EINPROGRESS:
|
||||||
|
return "Operation in progress";
|
||||||
|
case EINTR:
|
||||||
|
return "Interrupted function call";
|
||||||
|
case EINVAL:
|
||||||
|
return "Invalid argument";
|
||||||
|
case EIO:
|
||||||
|
return "Input/output error";
|
||||||
|
case EISCONN:
|
||||||
|
return "Socket is connected";
|
||||||
|
case EISDIR:
|
||||||
|
return "Is a directory";
|
||||||
|
case ELOOP:
|
||||||
|
return "Symbolic link loop";
|
||||||
|
case EMFILE:
|
||||||
|
return "File descriptor value too large or too many open streams";
|
||||||
|
case EMLINK:
|
||||||
|
return "Too many links";
|
||||||
|
case EMSGSIZE:
|
||||||
|
return "Message too large";
|
||||||
|
case ENAMETOOLONG:
|
||||||
|
return "Filename too long";
|
||||||
|
case ENETDOWN:
|
||||||
|
return "Network is down";
|
||||||
|
case ENETRESET:
|
||||||
|
return "The connection was aborted by the network";
|
||||||
|
case ENETUNREACH:
|
||||||
|
return "Network unreachable";
|
||||||
|
case ENFILE:
|
||||||
|
return "Too many files open in system";
|
||||||
|
case ENOBUFS:
|
||||||
|
return "No buffer space available";
|
||||||
|
case ENODATA:
|
||||||
|
return "No message available";
|
||||||
|
case ENODEV:
|
||||||
|
return "No such device";
|
||||||
|
case ENOENT:
|
||||||
|
return "No such file or directory";
|
||||||
|
case ENOEXEC:
|
||||||
|
return "Executable file format error";
|
||||||
|
case ENOLCK:
|
||||||
|
return "No locks available";
|
||||||
|
case ENOMEM:
|
||||||
|
return "Not enough space";
|
||||||
|
case ENOMSG:
|
||||||
|
return "No message of the desired type";
|
||||||
|
case ENOPROTOOPT:
|
||||||
|
return "Protocol not available";
|
||||||
|
case ENOSPC:
|
||||||
|
return "No space left on device";
|
||||||
|
case ENOSR:
|
||||||
|
return "No STREAM resources";
|
||||||
|
case ENOSTR:
|
||||||
|
return "Not a STREAM";
|
||||||
|
case ENOSYS:
|
||||||
|
return "Functionality not supported";
|
||||||
|
case ENOTCONN:
|
||||||
|
return "Socket not connected";
|
||||||
|
case ENOTDIR:
|
||||||
|
return "Not a directory";
|
||||||
|
case ENOTEMPTY:
|
||||||
|
return "Directory not empty";
|
||||||
|
case ENOTRECOVERABLE:
|
||||||
|
return "State not recoverable";
|
||||||
|
case ENOTSOCK:
|
||||||
|
return "Not a socket";
|
||||||
|
case ENOTSUP:
|
||||||
|
return "Not supported";
|
||||||
|
case ENOTTY:
|
||||||
|
return "Inappropriate I/O control operation";
|
||||||
|
case ENXIO:
|
||||||
|
return "No such device or address";
|
||||||
|
case EOPNOTSUPP:
|
||||||
|
return "Operation not supported on socket";
|
||||||
|
case EOVERFLOW:
|
||||||
|
return "Value too large to be stored in data type";
|
||||||
|
case EOWNERDEAD:
|
||||||
|
return "Previous owner died";
|
||||||
|
case EPERM:
|
||||||
|
return "Operation not permitted";
|
||||||
|
case EPIPE:
|
||||||
|
return "Broken pipe";
|
||||||
|
case EPROTO:
|
||||||
|
return "Protocol error";
|
||||||
|
case EPROTONOSUPPORT:
|
||||||
|
return "Protocol not supported";
|
||||||
|
case EPROTOTYPE:
|
||||||
|
return "Protocol wrong type for socket";
|
||||||
|
case ERANGE:
|
||||||
|
return "Result too large";
|
||||||
|
case EROFS:
|
||||||
|
return "Read-only file system";
|
||||||
|
case ESPIPE:
|
||||||
|
return "Invalid seek";
|
||||||
|
case ESRCH:
|
||||||
|
return "No such process";
|
||||||
|
case ETIME:
|
||||||
|
return "STREAM ioctl() timeout";
|
||||||
|
case ETIMEDOUT:
|
||||||
|
return "Connection timed out";
|
||||||
|
case ETXTBSY:
|
||||||
|
return "Text file busy";
|
||||||
|
case EWOULDBLOCK:
|
||||||
|
return "Operation would block";
|
||||||
|
case EXDEV:
|
||||||
|
return "Improper link";
|
||||||
|
default:
|
||||||
|
snprintf(unknown_error, sizeof(unknown_error), "Unknown error %d", errnum);
|
||||||
|
return unknown_error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export char *strerror_l(int errnum, locale_t locale);
|
||||||
|
|
||||||
|
export int strerror_r(int errnum, char *strerrbuf, size_t buflen)
|
||||||
|
{
|
||||||
|
const char *errmsg = strerror(errnum);
|
||||||
|
if (strlen(errmsg) >= buflen)
|
||||||
|
{
|
||||||
|
if (buflen > 0)
|
||||||
|
{
|
||||||
|
strncpy(strerrbuf, errmsg, buflen - 1);
|
||||||
|
strerrbuf[buflen - 1] = '\0';
|
||||||
|
}
|
||||||
|
return ERANGE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
strcpy(strerrbuf, errmsg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t strlcat(char *restrict dst, const char *restrict src, size_t dstsize)
|
||||||
|
{
|
||||||
|
size_t dst_len = strnlen(dst, dstsize);
|
||||||
|
size_t src_len = strlen(src);
|
||||||
|
|
||||||
|
if (dst_len == dstsize)
|
||||||
|
return dstsize + src_len;
|
||||||
|
|
||||||
|
if (src_len < dstsize - dst_len)
|
||||||
|
memcpy(dst + dst_len, src, src_len + 1);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memcpy(dst + dst_len, src, dstsize - dst_len - 1);
|
||||||
|
dst[dstsize - 1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return dst_len + src_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t strlcpy(char *restrict dst, const char *restrict src, size_t dstsize)
|
||||||
|
{
|
||||||
|
size_t src_len = strlen(src);
|
||||||
|
|
||||||
|
if (dstsize != 0)
|
||||||
|
{
|
||||||
|
size_t copy_len = (src_len >= dstsize) ? dstsize - 1 : src_len;
|
||||||
|
memcpy(dst, src, copy_len);
|
||||||
|
dst[copy_len] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return src_len;
|
||||||
|
}
|
||||||
|
|
||||||
export size_t strlen(const char *s)
|
export size_t strlen(const char *s)
|
||||||
{
|
{
|
||||||
@ -126,7 +468,18 @@ export size_t strlen(const char *s)
|
|||||||
return s - start;
|
return s - start;
|
||||||
}
|
}
|
||||||
|
|
||||||
export char *strncat(char *restrict, const char *restrict, size_t);
|
export char *strncat(char *restrict s1, const char *restrict s2, size_t n)
|
||||||
|
{
|
||||||
|
char *dest = s1;
|
||||||
|
while (*dest)
|
||||||
|
dest++;
|
||||||
|
|
||||||
|
while (n-- && *s2)
|
||||||
|
*dest++ = *s2++;
|
||||||
|
|
||||||
|
*dest = '\0';
|
||||||
|
return s1;
|
||||||
|
}
|
||||||
|
|
||||||
export int strncmp(const char *s1, const char *s2, size_t n)
|
export int strncmp(const char *s1, const char *s2, size_t n)
|
||||||
{
|
{
|
||||||
@ -155,8 +508,24 @@ export char *strncpy(char *restrict s1, const char *restrict s2, size_t n)
|
|||||||
return s1;
|
return s1;
|
||||||
}
|
}
|
||||||
|
|
||||||
export char *strndup(const char *, size_t);
|
export char *strndup(const char *s, size_t size)
|
||||||
export size_t strnlen(const char *, size_t);
|
{
|
||||||
|
size_t len = strnlen(s, size);
|
||||||
|
char *new_str = (char *)malloc(len + 1);
|
||||||
|
if (!new_str)
|
||||||
|
return NULL;
|
||||||
|
memcpy(new_str, s, len);
|
||||||
|
new_str[len] = '\0';
|
||||||
|
return new_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
export size_t strnlen(const char *s, size_t maxlen)
|
||||||
|
{
|
||||||
|
size_t len = 0;
|
||||||
|
while (len < maxlen && s[len] != '\0')
|
||||||
|
len++;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
export char *strpbrk(const char *s1, const char *s2)
|
export char *strpbrk(const char *s1, const char *s2)
|
||||||
{
|
{
|
||||||
@ -174,7 +543,16 @@ export char *strpbrk(const char *s1, const char *s2)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
export char *strrchr(const char *, int);
|
export char *strrchr(const char *s, int c)
|
||||||
|
{
|
||||||
|
const char *last = NULL;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (*s == (char)c)
|
||||||
|
last = s;
|
||||||
|
} while (*s++);
|
||||||
|
return (char *)last;
|
||||||
|
}
|
||||||
|
|
||||||
export char *strsignal(int signum)
|
export char *strsignal(int signum)
|
||||||
{
|
{
|
||||||
@ -259,7 +637,28 @@ cont:
|
|||||||
return p - 1 - s1;
|
return p - 1 - s1;
|
||||||
}
|
}
|
||||||
|
|
||||||
export char *strstr(const char *, const char *);
|
export char *strstr(const char *s1, const char *s2)
|
||||||
|
{
|
||||||
|
if (!*s2)
|
||||||
|
return (char *)s1;
|
||||||
|
|
||||||
|
for (; *s1; s1++)
|
||||||
|
{
|
||||||
|
const char *h = s1;
|
||||||
|
const char *n = s2;
|
||||||
|
|
||||||
|
while (*h && *n && *h == *n)
|
||||||
|
{
|
||||||
|
h++;
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!*n)
|
||||||
|
return (char *)s1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
export char *strtok(char *restrict s, const char *restrict sep)
|
export char *strtok(char *restrict s, const char *restrict sep)
|
||||||
{
|
{
|
||||||
@ -295,5 +694,19 @@ export char *strtok_r(char *restrict s, const char *restrict sep, char **restric
|
|||||||
return start;
|
return start;
|
||||||
}
|
}
|
||||||
|
|
||||||
export size_t strxfrm(char *restrict, const char *restrict, size_t);
|
export size_t strxfrm(char *restrict s1, const char *restrict s2, size_t n)
|
||||||
export size_t strxfrm_l(char *restrict, const char *restrict, size_t, locale_t);
|
{
|
||||||
|
size_t len = 0;
|
||||||
|
while (s2[len] != '\0' && len < n - 1)
|
||||||
|
{
|
||||||
|
s1[len] = s2[len];
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
if (n > 0)
|
||||||
|
s1[len] = '\0';
|
||||||
|
while (s2[len] != '\0')
|
||||||
|
len++;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
export size_t strxfrm_l(char *restrict s1, const char *restrict s2, size_t n, locale_t locale);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user