aboutsummaryrefslogtreecommitdiff
path: root/src/string.c
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2024-05-24 13:24:27 +0300
committerKimplul <kimi.h.kuparinen@gmail.com>2024-05-24 18:13:43 +0300
commitbc600ecc3bdf0f189861dfb840f70c2339a7a853 (patch)
treed9840b1dc1b865442a028c03ad7109ac67894f6e /src/string.c
parent6a7073e5f262db9a4578ff00b5b28e34335564ce (diff)
downloadkmi-bc600ecc3bdf0f189861dfb840f70c2339a7a853.tar.gz
kmi-bc600ecc3bdf0f189861dfb840f70c2339a7a853.zip
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
Diffstat (limited to 'src/string.c')
-rw-r--r--src/string.c463
1 files changed, 463 insertions, 0 deletions
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 <kmi/string.h>
+#include <kmi/types.h>
+#include <kmi/attrs.h>
+
+/* 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);
+}