aboutsummaryrefslogtreecommitdiff
path: root/lib/mlibc/options/posix/generic/posix_string.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/mlibc/options/posix/generic/posix_string.cpp')
-rw-r--r--lib/mlibc/options/posix/generic/posix_string.cpp174
1 files changed, 174 insertions, 0 deletions
diff --git a/lib/mlibc/options/posix/generic/posix_string.cpp b/lib/mlibc/options/posix/generic/posix_string.cpp
new file mode 100644
index 0000000..d0bc7b5
--- /dev/null
+++ b/lib/mlibc/options/posix/generic/posix_string.cpp
@@ -0,0 +1,174 @@
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <bits/ensure.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <signal.h>
+
+#include <mlibc/debug.hpp>
+
+char *strdup(const char *string) {
+ auto num_bytes = strlen(string);
+
+ char *new_string = (char *)malloc(num_bytes + 1);
+ if(!new_string) // TODO: set errno
+ return nullptr;
+
+ memcpy(new_string, string, num_bytes);
+ new_string[num_bytes] = 0;
+ return new_string;
+}
+
+char *strndup(const char *string, size_t max_size) {
+ auto num_bytes = strnlen(string, max_size);
+ char *new_string = (char *)malloc(num_bytes + 1);
+ if(!new_string) // TODO: set errno
+ return nullptr;
+
+ memcpy(new_string, string, num_bytes);
+ new_string[num_bytes] = 0;
+ return new_string;
+}
+
+char *stpcpy(char *__restrict dest, const char *__restrict src) {
+ auto n = strlen(src);
+ memcpy(dest, src, n + 1);
+ return dest + n;
+}
+
+char *stpncpy(char *__restrict dest, const char *__restrict src, size_t n) {
+ size_t nulls, copied, srcLen = strlen(src);
+ if (n >= srcLen) {
+ nulls = n - srcLen;
+ copied = srcLen;
+ } else {
+ nulls = 0;
+ copied = n;
+ }
+
+ memcpy(dest, src, copied);
+ memset(dest + srcLen, 0, nulls);
+ return dest + n - nulls;
+}
+
+size_t strnlen(const char *s, size_t n) {
+ size_t len = 0;
+ while(len < n && s[len])
+ ++len;
+ return len;
+}
+
+char *strsep(char **m, const char *del) {
+ __ensure(m);
+
+ auto tok = *m;
+ if(!tok)
+ return nullptr;
+
+ // Replace the following delimiter by a null-terminator.
+ // After this loop: *p is null iff we reached the end of the string.
+ auto p = tok;
+ while(*p && !strchr(del, *p))
+ p++;
+
+ if(*p) {
+ *p = 0;
+ *m = p + 1;
+ }else{
+ *m = nullptr;
+ }
+ return tok;
+}
+
+char *strsignal(int sig) {
+ #define CASE_FOR(sigconst) case sigconst: s = #sigconst; break;
+ const char *s;
+ switch(sig) {
+ CASE_FOR(SIGABRT)
+ CASE_FOR(SIGFPE)
+ CASE_FOR(SIGILL)
+ CASE_FOR(SIGINT)
+ CASE_FOR(SIGSEGV)
+ CASE_FOR(SIGTERM)
+ CASE_FOR(SIGPROF)
+ CASE_FOR(SIGIO)
+ CASE_FOR(SIGPWR)
+ CASE_FOR(SIGALRM)
+ CASE_FOR(SIGBUS)
+ CASE_FOR(SIGCHLD)
+ CASE_FOR(SIGCONT)
+ CASE_FOR(SIGHUP)
+ CASE_FOR(SIGKILL)
+ CASE_FOR(SIGPIPE)
+ CASE_FOR(SIGQUIT)
+ CASE_FOR(SIGSTOP)
+ CASE_FOR(SIGTSTP)
+ CASE_FOR(SIGTTIN)
+ CASE_FOR(SIGTTOU)
+ CASE_FOR(SIGUSR1)
+ CASE_FOR(SIGUSR2)
+ CASE_FOR(SIGSYS)
+ CASE_FOR(SIGTRAP)
+ CASE_FOR(SIGURG)
+ CASE_FOR(SIGVTALRM)
+ CASE_FOR(SIGXCPU)
+ CASE_FOR(SIGXFSZ)
+ CASE_FOR(SIGWINCH)
+ default:
+ mlibc::infoLogger() << "mlibc: Unknown signal number " << sig << frg::endlog;
+ s = "Unknown signal number";
+ }
+ return const_cast<char *>(s);
+}
+
+char *strcasestr(const char *s, const char *pattern) {
+ size_t plen = strlen(pattern);
+ const char *p = s;
+ while(*p) {
+ // Need strncasecmp() to avoid checking past the end of a successful match.
+ if(!strncasecmp(p, pattern, plen))
+ return const_cast<char *>(p);
+ ++p;
+ }
+ return nullptr;
+}
+
+void *memccpy(void *__restrict, const void *__restrict, int, size_t) {
+ __ensure(!"Not implemented");
+ __builtin_unreachable();
+}
+
+// This implementation was taken from musl
+void *memrchr(const void *m, int c, size_t n) {
+ const unsigned char *s = (const unsigned char *)m;
+ c = (unsigned char)c;
+ while(n--) {
+ if(s[n] == c)
+ return (void *)(s + n);
+ }
+ return 0;
+}
+
+// BSD extensions.
+// Taken from musl
+size_t strlcpy(char *d, const char *s, size_t n) {
+ char *d0 = d;
+
+ if(!n--)
+ goto finish;
+ for(; n && (*d=*s); n--, s++, d++);
+ *d = 0;
+finish:
+ return d-d0 + strlen(s);
+}
+
+size_t strlcat(char *d, const char *s, size_t n) {
+ size_t l = strnlen(d, n);
+ if(l == n) {
+ return l + strlen(s);
+ }
+ return l + strlcpy(d + l, s, n - l);
+}