From bc600ecc3bdf0f189861dfb840f70c2339a7a853 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Fri, 24 May 2024 13:24:27 +0300 Subject: rename common to src + I keep starting to type src and wondering why autocomplete won't work, I guess src is just uncounciously a better name --- src/string.c | 463 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 463 insertions(+) create mode 100644 src/string.c (limited to 'src/string.c') diff --git a/src/string.c b/src/string.c new file mode 100644 index 0000000..8c88e65 --- /dev/null +++ b/src/string.c @@ -0,0 +1,463 @@ +/* SPDX-License-Identifier: copyleft-next-0.3.1 */ +/* Copyright 2021 - 2022, Kim Kuparinen < kimi.h.kuparinen@gmail.com > */ + +/** + * @file string.c + * Implementations of some string.h stdlib functions. + */ + +#include +#include +#include + +/* we need to undef the macros in string.h, otherwise the names get mangled */ +#undef strcpy +__weak char *strcpy(char * restrict dst, const char * restrict src) +{ + const char *s1 = src; + char *s2 = dst; + + while (*s1) + *(s2++) = *(s1++); + + return dst; +} + +#undef strncpy +__weak char *strncpy(char * restrict dst, const char * restrict src, size_t num) +{ + const char *s1 = src; + char *s2 = dst; + + /* copy s1 into s2 */ + while (num-- && *s1) + *(s2++) = *(s1++); + + /* the previous loop always overshoots by one */ + num++; + + /* pad with zeroes if num is not yet zero */ + while (num--) + *(s2++) = 0; + + return dst; +} + +#undef strcat +__weak char *strcat(char * restrict dst, const char * restrict src) +{ + const char *s1 = src; + size_t l1 = strlen(s1); + char *s2 = dst + l1; + + while (*s1) + *(s2++) = *(s1++); + + /* append null character */ + *s2 = 0; + + return dst; +} + +#undef strncat +__weak char *strncat(char * restrict dst, const char * restrict src, size_t num) +{ + const char *s1 = src; + size_t l1 = strlen(s1); + char *s2 = dst + l1; + + while (num-- && *s1) + *(s2++) = *(s1++); + + /* append null character */ + *s2 = 0; + + return dst; +} + +#undef strcmp +__weak int strcmp(const char *str1, const char *str2) +{ + const char *s1 = (const char *)str1; + const char *s2 = (const char *)str2; + + while ((*(s1++) == *(s2++)) && *s1 && *s2) + ; + + return (int)(s1[-1] - s2[-1]); +} + +#undef strncmp +__weak int strncmp(const char *str1, const char *str2, size_t num) +{ + const char *s1 = (const char *)str1; + const char *s2 = (const char *)str2; + + while ((*(s1++) == *(s2++)) && *s1 && *s2 && --num) + ; + + return (int)(s1[-1] - s2[-1]); +} + +#undef strchr +__weak char *strchr(const char *str, int chr) +{ + const char *s1 = str; + ssize_t num = strlen(s1); + + while (num-- && *(s1++) != chr) + ; + + if (num < 0) + return 0; + + return (char *)(s1 - 1); +} + +#undef strtok +__weak char *strtok(char * restrict str, const char * restrict delims) +{ + static char *cont = 0; + const char *s1 = str; + + if (!s1) + s1 = cont; + + if (!s1) + return 0; + + s1 = strpbrk(s1, delims); + + if (!s1) + cont = 0; + else + cont = (char *)s1 + 1; + + return (char *)s1; +} + +/* should probably test out these functions somehwere, blergh */ +#undef strstr +__weak char *strstr(const char *str1, const char *str2) +{ + /* boyer-moore-horspool */ + char table[256] = { 0 }; + size_t sl = strlen(str1); + size_t pl = strlen(str2); + + const unsigned char *s1 = (const unsigned char *)str1; + const unsigned char *haystack = (const unsigned char *)s1; + const unsigned char *needle = (const unsigned char *)str2; + + for (size_t i = 0; i < 256; ++i) + table[i] = pl; + + /* generate deltas */ + for (size_t i = 0; i < pl - 1; ++i) + table[needle[i]] = pl - i - 1; + + size_t skip = 0; + while (sl - skip >= pl) { + s1 = &haystack[skip]; + + if (!memcmp(s1, needle, pl)) + return (char *)s1; + + skip += table[haystack[skip + pl - 1]]; + } + + return 0; +} + +#undef strrchr +__weak char *strrchr(const char *str, int chr) +{ + ssize_t num = strlen(str); + const char *s1 = (str + num) - 1; + + while (num-- && *(s1--) != chr) + ; + + if (num < 0) + return 0; + + return (char *)(s1 + 1); +} + +#undef strpbrk +__weak char *strpbrk(const char *str1, const char *str2) +{ + size_t i = strcspn(str1, str2); + + if (!i) + return 0; + + return (char *)(str1 + i); +} + +#undef strcspn +__weak size_t strcspn(const char *str1, const char *str2) +{ + char table[256] = { 0 }; + const unsigned char *s1 = (const unsigned char *)str1; + const unsigned char *s2 = (const unsigned char *)s1; + const unsigned char *t1 = (const unsigned char *)str2; + + /* populate table */ + while (*(t1++)) + table[*t1] = 1; + + for (;;) { + if (table[*(s2++)]) + break; + } + + /* the for loop overshoots by one */ + return (size_t)(s2 - s1) - 1; +} + +#undef strspn +__weak size_t strspn(const char *str1, const char *str2) +{ + char table[256] = { 0 }; + const unsigned char *s1 = (const unsigned char *)str1; + const unsigned char *s2 = (const unsigned char *)s1; + const unsigned char *t1 = (const unsigned char *)str2; + + /* populate table */ + while (*(t1++)) + table[*t1] = 1; + + for (;;) { + if (!table[*(s2++)]) + break; + } + + /* the for loop overshoots by one */ + return (size_t)(s2 - s1) - 1; +} + +#undef strlen +__weak size_t strlen(const char *str) +{ + const char *s1 = str; + while (*(s1++)) + ; + + /* the loop overshoots by one */ + return (size_t)(s1 - str) - 1; +} + +/* not a macro */ +__weak size_t strnlen(const char *str, size_t num) +{ + const char *s1 = str; + while (num-- && *(s1++)) + ; + + return (size_t)(s1 - str) - 1; +} + +#undef memset +__weak void *memset(void *ptr, int value, size_t num) +{ + char *p = ptr; + char c = value; + + while (num--) + *(p++) = c; + + return ptr; +} + +#undef memchr +__weak void *memchr(const void *ptr, int val, size_t num) +{ + const char *p1 = (char *)ptr; + ssize_t n = num; + char c = (char)val; + + while (n-- && *(p1++) != c) + ; + + if (n < 0) + return 0; + + return (void *)(p1 - 1); +} + +#undef memcpy +__weak void *memcpy(void * restrict dst, const void * restrict src, size_t num) +{ + const char *m1 = (const char *)src; + char *m2 = (char *)dst; + + while (num--) + *(m2++) = *(m1++); + + return dst; +} + +#undef memmove +__weak void *memmove(void *dst, const void *src, size_t num) +{ + const char *m1 = (const char *)src; + char *m2 = (char *)dst; + + m1 += num; + m2 += num; + + /* doesn't really take into account aliasing yet */ + while (num--) + *(--m2) = *(--m1); + + return dst; +} + +#undef memcmp +__weak int memcmp(const void *ptr1, const void *ptr2, size_t num) +{ + const char *p1 = (const char *)ptr1; + const char *p2 = (const char *)ptr2; + + while ((*(p1++) == *(p2++)) && --num) + ; + + return (int)(p1[-1] - p2[-1]); +} + +/** + * Convert ASCII hex character to integer. + * Allows both upper- and lowercase letters. + * + * @param c Character to convert. + * @return Corresponding integer value. That is, '1' => 1, '2' => 2, etc. + * \c -1 if conversion failed. + */ +static int __hexval(char c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + + if (c >= 'a' && c <= 'f') + return 10 + c - 'a'; + + if (c >= 'A' && c <= 'F') + return 10 + c - 'A'; + + return -1; +} + +/** + * Convert string assumed to represent hex + * value to corresponding pointer. + * + * @param s String to convert to value. + * @return Corresponding pointer value. + */ +static uintptr_t __hexuintptr(const char *s) +{ + uintptr_t res = 0; + int val = 0; + while ((val = __hexval(*(s++))) != -1) { + res *= 16; + res += val; + } + + return res; +} + +/** + * Convert ASCII decimal character to integer. + * + * @param c Character to convert. + * @return Corresponding integer value. That is, '1' => 1, '2' => 2, etc. + * \c -1 if conversion failed. + */ +static int __decval(char c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + + return -1; +} + +/** + * Convert string assumed to represent decimal + * value to corresponding pointer. + * + * @param s String to convert to value. + * @return Corresponding pointer value. + */ +static uintptr_t __decuintptr(const char *s) +{ + uintptr_t res = 0; + int val = 0; + while ((val = __decval(*(s++))) != -1) { + res *= 10; + res += val; + } + + return res; +} + +/** + * Convert ASCII octal character to integer. + * + * @param c Character to convert. + * @return Corresponding integer value. That is, '1' => 1, '2' => 2, etc. + * \c -1 if conversion failed. + */ +static int __octval(char c) +{ + if (c >= '0' && c <= '7') + return c - '0'; + + return -1; +} + +/** + * Convert string assumed to represent octal + * value to corresponding pointer. + * + * @param s String to convert to value. + * @return Corresponding pointer value. + */ +static uintptr_t __octuintptr(const char *s) +{ + uintptr_t res = 0; + int val = 0; + while ((val = __octval(*(s++))) != -1) { + res *= 8; + res += val; + } + + return res; +} + +uintptr_t strtouintptr(const char *s) +{ + if (!s) + return 0; + + if (s[0] == 0) + return 0; + + if (s[0] == '0') { + if (s[1] == 0) + return 0; + + if (s[1] == 'x' || s[1] == 'X') + return __hexuintptr(s + 2); + + return __octuintptr(s + 1); + } + + if (s[0] == '-') + return -__decuintptr(s + 1); + + if (s[0] == '+') + return __decuintptr(s + 1); + + return __decuintptr(s); +} -- cgit v1.3