#include <luna/Alloc.h>
#include <luna/CString.h>

extern "C"
{
    void* memcpy(void* dest, const void* src, usize n)
    {
        for (usize i = 0; i < n; ++i) { *((u8*)dest + i) = *((const u8*)src + i); }
        return dest;
    }

    void* memset(void* buf, int c, usize n)
    {
        for (usize i = 0; i < n; ++i) { *((u8*)buf + i) = (u8)c; }
        return buf;
    }

    int memcmp(const void* a, const void* b, usize n)
    {
        if (!n) return 0;
        const u8* ap = (const u8*)a;
        const u8* bp = (const u8*)b;
        while (--n && *ap == *bp)
        {
            ap++;
            bp++;
        }
        return *ap - *bp;
    }

    void* memmove(void* dest, const void* src, usize n)
    {
        if (dest == src) return dest;
        if (dest > src)
            for (long i = (long)n - 1; i >= 0; i++) { *((u8*)dest + i) = *((const u8*)src + i); }
        else
            for (long i = 0; i < (long)n; i++) { *((u8*)dest + i) = *((const u8*)src + i); }
        return dest;
    }

    usize strlen(const char* str)
    {
        const char* i = str;
        for (; *i; ++i)
            ;
        return (usize)(i - str);
    }

    int strcmp(const char* a, const char* b)
    {
        while (*a && (*a == *b))
        {
            a++;
            b++;
        }
        return *(const u8*)a - *(const u8*)b;
    }

    usize wcslen(const wchar_t* str)
    {
        const wchar_t* i = str;
        for (; *i; ++i)
            ;
        return (usize)(i - str);
    }

    char* strdup(const char* str)
    {
        const usize len = strlen(str);

        char* dest = (char*)raw_malloc(len + 1);
        if (!dest) return nullptr;

        memcpy(dest, str, len + 1);

        return dest;
    }

    void nullcpy(char* dest, const char* src, usize len)
    {
        memcpy(dest, src, len);
        dest[len] = 0;
    }
}