mirror of
https://github.com/EnderIce2/Fennix.git
synced 2025-07-16 09:41:42 +00:00
Update files
This commit is contained in:
442
Library/String.c
Normal file
442
Library/String.c
Normal file
@@ -0,0 +1,442 @@
|
||||
#include <string.h>
|
||||
#include <types.h>
|
||||
|
||||
// TODO: Replace mem* with assembly code
|
||||
|
||||
/* Some of the functions are from musl library */
|
||||
/* https://www.musl-libc.org/ */
|
||||
/*
|
||||
Copyright © 2005-2020 Rich Felker, et al.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
void *memcpy(void *dest, const void *src, size_t n)
|
||||
{
|
||||
unsigned char *d = dest;
|
||||
const unsigned char *s = src;
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#define LS >>
|
||||
#define RS <<
|
||||
#else
|
||||
#define LS <<
|
||||
#define RS >>
|
||||
#endif
|
||||
|
||||
typedef uint32_t __attribute__((__may_alias__)) u32;
|
||||
uint32_t w, x;
|
||||
|
||||
for (; (uintptr_t)s % 4 && n; n--)
|
||||
*d++ = *s++;
|
||||
|
||||
if ((uintptr_t)d % 4 == 0)
|
||||
{
|
||||
for (; n >= 16; s += 16, d += 16, n -= 16)
|
||||
{
|
||||
*(u32 *)(d + 0) = *(u32 *)(s + 0);
|
||||
*(u32 *)(d + 4) = *(u32 *)(s + 4);
|
||||
*(u32 *)(d + 8) = *(u32 *)(s + 8);
|
||||
*(u32 *)(d + 12) = *(u32 *)(s + 12);
|
||||
}
|
||||
if (n & 8)
|
||||
{
|
||||
*(u32 *)(d + 0) = *(u32 *)(s + 0);
|
||||
*(u32 *)(d + 4) = *(u32 *)(s + 4);
|
||||
d += 8;
|
||||
s += 8;
|
||||
}
|
||||
if (n & 4)
|
||||
{
|
||||
*(u32 *)(d + 0) = *(u32 *)(s + 0);
|
||||
d += 4;
|
||||
s += 4;
|
||||
}
|
||||
if (n & 2)
|
||||
{
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
}
|
||||
if (n & 1)
|
||||
{
|
||||
*d = *s;
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
if (n >= 32)
|
||||
switch ((uintptr_t)d % 4)
|
||||
{
|
||||
case 1:
|
||||
w = *(u32 *)s;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
n -= 3;
|
||||
for (; n >= 17; s += 16, d += 16, n -= 16)
|
||||
{
|
||||
x = *(u32 *)(s + 1);
|
||||
*(u32 *)(d + 0) = (w LS 24) | (x RS 8);
|
||||
w = *(u32 *)(s + 5);
|
||||
*(u32 *)(d + 4) = (x LS 24) | (w RS 8);
|
||||
x = *(u32 *)(s + 9);
|
||||
*(u32 *)(d + 8) = (w LS 24) | (x RS 8);
|
||||
w = *(u32 *)(s + 13);
|
||||
*(u32 *)(d + 12) = (x LS 24) | (w RS 8);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
w = *(u32 *)s;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
n -= 2;
|
||||
for (; n >= 18; s += 16, d += 16, n -= 16)
|
||||
{
|
||||
x = *(u32 *)(s + 2);
|
||||
*(u32 *)(d + 0) = (w LS 16) | (x RS 16);
|
||||
w = *(u32 *)(s + 6);
|
||||
*(u32 *)(d + 4) = (x LS 16) | (w RS 16);
|
||||
x = *(u32 *)(s + 10);
|
||||
*(u32 *)(d + 8) = (w LS 16) | (x RS 16);
|
||||
w = *(u32 *)(s + 14);
|
||||
*(u32 *)(d + 12) = (x LS 16) | (w RS 16);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
w = *(u32 *)s;
|
||||
*d++ = *s++;
|
||||
n -= 1;
|
||||
for (; n >= 19; s += 16, d += 16, n -= 16)
|
||||
{
|
||||
x = *(u32 *)(s + 3);
|
||||
*(u32 *)(d + 0) = (w LS 8) | (x RS 24);
|
||||
w = *(u32 *)(s + 7);
|
||||
*(u32 *)(d + 4) = (x LS 8) | (w RS 24);
|
||||
x = *(u32 *)(s + 11);
|
||||
*(u32 *)(d + 8) = (w LS 8) | (x RS 24);
|
||||
w = *(u32 *)(s + 15);
|
||||
*(u32 *)(d + 12) = (x LS 8) | (w RS 24);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (n & 16)
|
||||
{
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
}
|
||||
if (n & 8)
|
||||
{
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
}
|
||||
if (n & 4)
|
||||
{
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
}
|
||||
if (n & 2)
|
||||
{
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
}
|
||||
if (n & 1)
|
||||
{
|
||||
*d = *s;
|
||||
}
|
||||
return dest;
|
||||
#endif
|
||||
|
||||
for (; n; n--)
|
||||
*d++ = *s++;
|
||||
return dest;
|
||||
}
|
||||
|
||||
void *memset(void *dest, int c, size_t n)
|
||||
{
|
||||
unsigned char *s = dest;
|
||||
size_t k;
|
||||
|
||||
if (!n)
|
||||
return dest;
|
||||
s[0] = c;
|
||||
s[n - 1] = c;
|
||||
if (n <= 2)
|
||||
return dest;
|
||||
s[1] = c;
|
||||
s[2] = c;
|
||||
s[n - 2] = c;
|
||||
s[n - 3] = c;
|
||||
if (n <= 6)
|
||||
return dest;
|
||||
s[3] = c;
|
||||
s[n - 4] = c;
|
||||
if (n <= 8)
|
||||
return dest;
|
||||
|
||||
k = -(uintptr_t)s & 3;
|
||||
s += k;
|
||||
n -= k;
|
||||
n &= -4;
|
||||
|
||||
#ifdef __GNUC__
|
||||
typedef uint32_t __attribute__((__may_alias__)) u32;
|
||||
typedef uint64_t __attribute__((__may_alias__)) u64;
|
||||
|
||||
u32 c32 = ((u32)-1) / 255 * (unsigned char)c;
|
||||
*(u32 *)(s + 0) = c32;
|
||||
*(u32 *)(s + n - 4) = c32;
|
||||
if (n <= 8)
|
||||
return dest;
|
||||
*(u32 *)(s + 4) = c32;
|
||||
*(u32 *)(s + 8) = c32;
|
||||
*(u32 *)(s + n - 12) = c32;
|
||||
*(u32 *)(s + n - 8) = c32;
|
||||
if (n <= 24)
|
||||
return dest;
|
||||
*(u32 *)(s + 12) = c32;
|
||||
*(u32 *)(s + 16) = c32;
|
||||
*(u32 *)(s + 20) = c32;
|
||||
*(u32 *)(s + 24) = c32;
|
||||
*(u32 *)(s + n - 28) = c32;
|
||||
*(u32 *)(s + n - 24) = c32;
|
||||
*(u32 *)(s + n - 20) = c32;
|
||||
*(u32 *)(s + n - 16) = c32;
|
||||
|
||||
k = 24 + ((uintptr_t)s & 4);
|
||||
s += k;
|
||||
n -= k;
|
||||
|
||||
u64 c64 = c32 | ((u64)c32 << 32);
|
||||
for (; n >= 32; n -= 32, s += 32)
|
||||
{
|
||||
*(u64 *)(s + 0) = c64;
|
||||
*(u64 *)(s + 8) = c64;
|
||||
*(u64 *)(s + 16) = c64;
|
||||
*(u64 *)(s + 24) = c64;
|
||||
}
|
||||
#else
|
||||
for (; n; n--, s++)
|
||||
*s = c;
|
||||
#endif
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
void *memmove(void *dest, const void *src, size_t n)
|
||||
{
|
||||
#ifdef __GNUC__
|
||||
typedef __attribute__((__may_alias__)) size_t WT;
|
||||
#define WS (sizeof(WT))
|
||||
#endif
|
||||
|
||||
char *d = dest;
|
||||
const char *s = src;
|
||||
|
||||
if (d == s)
|
||||
return d;
|
||||
if ((uintptr_t)s - (uintptr_t)d - n <= -2 * n)
|
||||
return memcpy(d, s, n);
|
||||
|
||||
if (d < s)
|
||||
{
|
||||
#ifdef __GNUC__
|
||||
if ((uintptr_t)s % WS == (uintptr_t)d % WS)
|
||||
{
|
||||
while ((uintptr_t)d % WS)
|
||||
{
|
||||
if (!n--)
|
||||
return dest;
|
||||
*d++ = *s++;
|
||||
}
|
||||
for (; n >= WS; n -= WS, d += WS, s += WS)
|
||||
*(WT *)d = *(WT *)s;
|
||||
}
|
||||
#endif
|
||||
for (; n; n--)
|
||||
*d++ = *s++;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef __GNUC__
|
||||
if ((uintptr_t)s % WS == (uintptr_t)d % WS)
|
||||
{
|
||||
while ((uintptr_t)(d + n) % WS)
|
||||
{
|
||||
if (!n--)
|
||||
return dest;
|
||||
d[n] = s[n];
|
||||
}
|
||||
while (n >= WS)
|
||||
n -= WS, *(WT *)(d + n) = *(WT *)(s + n);
|
||||
}
|
||||
#endif
|
||||
while (n)
|
||||
n--, d[n] = s[n];
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
int memcmp(const void *vl, const void *vr, size_t n)
|
||||
{
|
||||
const unsigned char *l = vl, *r = vr;
|
||||
for (; n && *l == *r; n--, l++, r++)
|
||||
;
|
||||
return n ? *l - *r : 0;
|
||||
}
|
||||
|
||||
int strncmp(const char *s1, const char *s2, size_t n)
|
||||
{
|
||||
for (size_t i = 0; i < n; i++)
|
||||
{
|
||||
char c1 = s1[i], c2 = s2[i];
|
||||
if (c1 != c2)
|
||||
return c1 - c2;
|
||||
if (!c1)
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
long unsigned strlen(const char s[])
|
||||
{
|
||||
long unsigned i = 0;
|
||||
while (s[i] != '\0')
|
||||
++i;
|
||||
return i;
|
||||
}
|
||||
|
||||
char *strcat(char *destination, const char *source)
|
||||
{
|
||||
if ((destination == NULL) && (source == NULL))
|
||||
return NULL;
|
||||
char *start = destination;
|
||||
while (*start != '\0')
|
||||
{
|
||||
start++;
|
||||
}
|
||||
while (*source != '\0')
|
||||
{
|
||||
*start++ = *source++;
|
||||
}
|
||||
*start = '\0';
|
||||
return destination;
|
||||
}
|
||||
|
||||
char *strcpy(char *destination, const char *source)
|
||||
{
|
||||
if (destination == NULL)
|
||||
return NULL;
|
||||
char *ptr = destination;
|
||||
while (*source != '\0')
|
||||
{
|
||||
*destination = *source;
|
||||
destination++;
|
||||
source++;
|
||||
}
|
||||
*destination = '\0';
|
||||
return ptr;
|
||||
}
|
||||
|
||||
char *strncpy(char *destination, const char *source, unsigned long num)
|
||||
{
|
||||
if (destination == NULL)
|
||||
return NULL;
|
||||
char *ptr = destination;
|
||||
while (*source && num--)
|
||||
{
|
||||
*destination = *source;
|
||||
destination++;
|
||||
source++;
|
||||
}
|
||||
*destination = '\0';
|
||||
return ptr;
|
||||
}
|
||||
|
||||
int strcmp(const char *l, const char *r)
|
||||
{
|
||||
for (; *l == *r && *l; l++, r++)
|
||||
;
|
||||
return *(unsigned char *)l - *(unsigned char *)r;
|
||||
}
|
||||
|
||||
char *strstr(const char *haystack, const char *needle)
|
||||
{
|
||||
const char *a = haystack, *b = needle;
|
||||
while (1)
|
||||
{
|
||||
if (!*b)
|
||||
return (char *)haystack;
|
||||
if (!*a)
|
||||
return NULL;
|
||||
if (*a++ != *b++)
|
||||
{
|
||||
a = ++haystack;
|
||||
b = needle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int isdigit(int c)
|
||||
{
|
||||
return c >= '0' && c <= '9';
|
||||
}
|
||||
|
||||
int isspace(int c)
|
||||
{
|
||||
return c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '\f' || c == '\v';
|
||||
}
|
||||
|
||||
int isempty(char *str)
|
||||
{
|
||||
if (strlen(str) == 0)
|
||||
return 1;
|
||||
while (*str != '\0')
|
||||
{
|
||||
if (!isspace(*str))
|
||||
return 0;
|
||||
str++;
|
||||
}
|
||||
return 1;
|
||||
}
|
Reference in New Issue
Block a user