304 lines
7.8 KiB
C++
304 lines
7.8 KiB
C++
#include <errno.h>
|
|
#include <luna.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
extern "C"
|
|
{
|
|
void* memcpy(void* dest, const void* src, size_t n)
|
|
{
|
|
for (size_t i = 0; i < n; ++i) { *((char*)dest + i) = *((const char*)src + i); }
|
|
return dest;
|
|
}
|
|
|
|
void* memset(void* buf, int c, size_t n)
|
|
{
|
|
for (size_t i = 0; i < n; ++i) { *((char*)buf + i) = (char)c; }
|
|
return buf;
|
|
}
|
|
|
|
void* memchr(const void* buf, int c, size_t n)
|
|
{
|
|
const char* s = (const char*)buf;
|
|
for (; n && *s != (char)c; s++, n--)
|
|
;
|
|
if (n) return (void*)(const_cast<char*>(s));
|
|
return NULL;
|
|
}
|
|
|
|
int memcmp(const void* a, const void* b, size_t n)
|
|
{
|
|
if (!n) return 0;
|
|
const unsigned char* ap = (const unsigned char*)a;
|
|
const unsigned char* bp = (const unsigned char*)b;
|
|
while (--n && *ap == *bp)
|
|
{
|
|
ap++;
|
|
bp++;
|
|
}
|
|
return *ap - *bp;
|
|
}
|
|
|
|
void* memmove(void* dest, const void* src, size_t n)
|
|
{
|
|
if (dest == src) return dest;
|
|
if (dest > src)
|
|
for (long i = n - 1; i >= 0; i++) { *((char*)dest + i) = *((const char*)src + i); }
|
|
else
|
|
for (long i = 0; i < (long)n; i++) { *((char*)dest + i) = *((const char*)src + i); }
|
|
return dest;
|
|
}
|
|
|
|
char* strdup(const char* str)
|
|
{
|
|
size_t len = strlen(str);
|
|
char* dest = (char*)malloc(len + 1);
|
|
if (!dest) return dest;
|
|
return (char*)memcpy(dest, str, len + 1);
|
|
}
|
|
|
|
char* strndup(const char* str, size_t max)
|
|
{
|
|
size_t len = strnlen(str, max);
|
|
char* dest = (char*)malloc(len + 1);
|
|
if (!dest) return dest;
|
|
memcpy(dest, str, len);
|
|
dest[len] = 0;
|
|
return dest;
|
|
}
|
|
|
|
size_t strlen(const char* str)
|
|
{
|
|
const char* i = str;
|
|
for (; *i; ++i)
|
|
;
|
|
return (i - str);
|
|
}
|
|
|
|
size_t strnlen(const char* str, size_t max)
|
|
{
|
|
char* p = (char*)memchr(str, 0, max);
|
|
return p ? p - str : max;
|
|
}
|
|
|
|
char* strcpy(char* dest, const char* src)
|
|
{
|
|
return (char*)memcpy(dest, src, strlen(src) + 1);
|
|
}
|
|
|
|
char* strncpy(char* dest, const char* src, size_t max)
|
|
{
|
|
size_t i;
|
|
for (i = 0; i < max && src[i] != 0; i++) dest[i] = src[i];
|
|
for (; i < max; i++) dest[i] = 0;
|
|
return dest;
|
|
}
|
|
|
|
size_t strlcpy(char* dest, const char* src, size_t size)
|
|
{
|
|
size_t len = strlen(src);
|
|
if (size == 0) return len;
|
|
if (len < (size - 1))
|
|
{
|
|
memcpy(dest, src, len);
|
|
dest[len] = 0;
|
|
}
|
|
else
|
|
{
|
|
memcpy(dest, src, size - 1);
|
|
dest[size - 1] = 0;
|
|
}
|
|
return len;
|
|
}
|
|
|
|
int strcmp(const char* a, const char* b)
|
|
{
|
|
while (*a && (*a == *b))
|
|
{
|
|
a++;
|
|
b++;
|
|
}
|
|
return *(const unsigned char*)a - *(const unsigned char*)b;
|
|
}
|
|
|
|
int strncmp(const char* a, const char* b, size_t max)
|
|
{
|
|
const char* base = a;
|
|
while (*a && (*a == *b) && (size_t)(a - base) < (max - 1))
|
|
{
|
|
a++;
|
|
b++;
|
|
}
|
|
return *(const unsigned char*)a - *(const unsigned char*)b;
|
|
}
|
|
|
|
int strcoll(const char* a, const char* b)
|
|
{
|
|
return strcmp(a, b);
|
|
}
|
|
|
|
size_t strxfrm(char* dest, const char* src, size_t n)
|
|
{
|
|
strncpy(dest, src, n);
|
|
return n;
|
|
}
|
|
|
|
size_t strcspn(const char* str, const char* reject)
|
|
{
|
|
const char* s = str;
|
|
while (*s)
|
|
{
|
|
const char* rp = reject;
|
|
while (*rp)
|
|
{
|
|
if (*s == *rp) return s - str;
|
|
rp++;
|
|
}
|
|
s++;
|
|
}
|
|
return s - str;
|
|
}
|
|
|
|
size_t strspn(const char* str, const char* accept)
|
|
{
|
|
const char* s = str;
|
|
while (*s)
|
|
{
|
|
const char* ap = accept;
|
|
bool match = false;
|
|
while (*ap)
|
|
{
|
|
if (*s == *ap)
|
|
{
|
|
match = true;
|
|
break;
|
|
}
|
|
ap++;
|
|
}
|
|
if (!match) return s - str;
|
|
s++;
|
|
}
|
|
return s - str;
|
|
}
|
|
|
|
char* strpbrk(const char* a, const char* b)
|
|
{
|
|
while (*a)
|
|
{
|
|
if (strchr(b, *a)) return const_cast<char*>(a);
|
|
a++;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
char* strcat(char* dest, const char* src)
|
|
{
|
|
size_t dest_len = strlen(dest);
|
|
size_t i;
|
|
|
|
for (i = 0; *(src + i); i++) *(char*)(dest + dest_len + i) = *(const char*)(src + i);
|
|
|
|
*(char*)(dest + dest_len + i) = '\0';
|
|
|
|
return dest;
|
|
}
|
|
|
|
char* strncat(char* dest, const char* src, size_t max)
|
|
{
|
|
size_t dest_len = strlen(dest);
|
|
size_t i;
|
|
|
|
for (i = 0; i < max && *(src + i); i++) *(char*)(dest + dest_len + i) = *(const char*)(src + i);
|
|
|
|
*(char*)(dest + dest_len + i) = '\0';
|
|
|
|
return dest;
|
|
}
|
|
|
|
char* strchr(const char* str, int c)
|
|
{
|
|
while (*str && *str != (char)c) str++;
|
|
if (*str) return const_cast<char*>(str);
|
|
return NULL;
|
|
}
|
|
|
|
char* strchrnul(const char* str, int c)
|
|
{
|
|
while (*str && *str != (char)c) str++;
|
|
return const_cast<char*>(str);
|
|
}
|
|
|
|
char* strrchr(const char* str, int c)
|
|
{
|
|
const char* s = str + strlen(str);
|
|
while (s != str && *s != (char)c) s--;
|
|
if (s != str) return const_cast<char*>(s);
|
|
if (*s == (char)c) return const_cast<char*>(s);
|
|
return NULL;
|
|
}
|
|
|
|
char* strstr(const char* haystack, const char* needle)
|
|
{
|
|
size_t needle_size = strlen(needle);
|
|
size_t haystack_size = strlen(haystack);
|
|
while (*haystack)
|
|
{
|
|
if (*haystack == *needle)
|
|
{
|
|
if (needle_size <= haystack_size)
|
|
{
|
|
if (!strncmp(haystack, needle, needle_size)) return const_cast<char*>(haystack);
|
|
}
|
|
else { return NULL; }
|
|
}
|
|
haystack++;
|
|
haystack_size--;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
#pragma GCC push_options
|
|
#pragma GCC diagnostic ignored "-Wwrite-strings"
|
|
|
|
char* strerror(int err)
|
|
{
|
|
switch (err)
|
|
{
|
|
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 "Input/output error";
|
|
case E2BIG: return "Argument list too long";
|
|
case ENOEXEC: return "Exec format error";
|
|
case EBADF: return "Bad file descriptor";
|
|
case ECHILD: return "No child processes";
|
|
case EAGAIN: return "Resource temporarily unavailable";
|
|
case ENOMEM: return "Cannot allocate memory";
|
|
case EACCES: return "Permission denied";
|
|
case EFAULT: return "Bad address";
|
|
case EEXIST: return "File exists";
|
|
case ENOTDIR: return "Not a directory";
|
|
case EISDIR: return "Is a directory";
|
|
case EINVAL: return "Invalid argument";
|
|
case EMFILE: return "Too many open files";
|
|
case ENOTTY: return "Inappropriate ioctl for device";
|
|
case EFBIG: return "File too large";
|
|
case ENOSPC: return "No space left on device";
|
|
case EPIPE: return "Broken pipe";
|
|
case EDOM: return "Numerical argument out of domain";
|
|
case ERANGE: return "Numerical result out of range";
|
|
case ENOSYS: return "Function not implemented";
|
|
case ENOTSUP: return "Operation not supported";
|
|
case 0: return "Success";
|
|
default: return "Unknown error";
|
|
}
|
|
}
|
|
|
|
#pragma GCC pop_options
|
|
|
|
char* strtok(char*, const char*)
|
|
{
|
|
NOT_IMPLEMENTED("strtok");
|
|
}
|
|
} |