diff options
Diffstat (limited to 'libs/libc/str.c')
-rw-r--r-- | libs/libc/str.c | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/libs/libc/str.c b/libs/libc/str.c new file mode 100644 index 0000000..ba16920 --- /dev/null +++ b/libs/libc/str.c @@ -0,0 +1,207 @@ +// MIT License, Copyright (c) 2020 Marvin Borner + +#include <def.h> +#include <errno.h> +#include <mem.h> +#include <str.h> + +u32 strlen(const char *s) +{ + const char *ss = s; + while (*ss) + ss++; + return ss - s; +} + +char *strcpy(char *dst, const char *src) +{ + char *q = dst; + const char *p = src; + char ch; + + do { + *q++ = ch = *p++; + } while (ch); + + return dst; +} + +char *strncpy(char *dst, const char *src, u32 n) +{ + char *q = dst; + + while (n-- && (*dst++ = *src++)) + ; + + return q; +} + +int strcmp(const char *s1, const char *s2) +{ + const u8 *c1 = (const u8 *)s1; + const u8 *c2 = (const u8 *)s2; + u8 ch; + int d = 0; + + while (1) { + d = (int)(ch = *c1++) - (int)*c2++; + if (d || !ch) + break; + } + + return d; +} + +int strncmp(const char *s1, const char *s2, u32 n) +{ + const u8 *c1 = (const u8 *)s1; + const u8 *c2 = (const u8 *)s2; + u8 ch; + int d = 0; + + while (n--) { + d = (int)(ch = *c1++) - (int)*c2++; + if (d || !ch) + break; + } + + return d; +} + +char *strchr(char *s, int c) +{ + while (*s != (char)c) { + if (!*s) + return NULL; + s++; + } + + return s; +} + +char *strrchr(char *s, int c) +{ + char *ret = 0; + + do { + if (*s == c) + ret = s; + } while (*s++); + + return ret; +} + +char *strcat(char *dst, const char *src) +{ + strcpy(strchr(dst, '\0'), src); + return dst; +} + +char *strncat(char *dst, const char *src, u32 n) +{ + strncpy(strchr(dst, '\0'), src, n); + return dst; +} + +char *strinv(char *s) +{ + u32 s_str = strlen(s); + + int iterations = (int)s_str / 2; + for (int i = 0; i < iterations; i++) { + char aux = s[i]; + s[i] = s[(s_str - i) - 1]; + s[(s_str - i) - 1] = aux; + } + return s; +} + +char *strdup(const char *s) +{ + int l = strlen(s) + 1; + char *d = malloc(l); + + memcpy(d, s, l); + + return d; +} + +const char *strerror(u32 error) +{ + switch (error) { + case 0: + return "Success"; + case EPERM: + return "Operation not permitted"; + case ENOENT: + return "No such file or directory"; + case ESRCH: + return "No such process"; + case EINTR: + return "Interrupted system call"; + case EIO: + return "I/O error"; + case ENXIO: + return "No such device or address"; + case E2BIG: + return "Argument list too long"; + case ENOEXEC: + return "Exec format error"; + case EBADF: + return "Bad file number"; + case ECHILD: + return "No child processes"; + case EAGAIN: + return "Try again"; + case ENOMEM: + return "Out of memory"; + case EACCES: + return "Permission denied"; + case EFAULT: + return "Bad address"; + case ENOTBLK: + return "Block device required"; + case EBUSY: + return "Device or resource busy"; + case EEXIST: + return "File exists"; + case EXDEV: + return "Cross-device link"; + case ENODEV: + return "No such device"; + case ENOTDIR: + return "Not a directory"; + case EISDIR: + return "Is a directory"; + case EINVAL: + return "Invalid argument"; + case ENFILE: + return "File table overflow"; + case EMFILE: + return "Too many open files"; + case ENOTTY: + return "Not a typewriter"; + case ETXTBSY: + return "Text file busy"; + case EFBIG: + return "File too large"; + case ENOSPC: + return "No space left on device"; + case ESPIPE: + return "Illegal seek"; + case EROFS: + return "Read-only file system"; + case EMLINK: + return "Too many links"; + case EPIPE: + return "Broken pipe"; + case EDOM: + return "Math argument out of domain of func"; + case ERANGE: + return "Math result not representable"; + case EMAX: + return "Max errno"; + default: + return "Unknown error"; + } +} |