#include <string.hpp>

int strncmp(const char* s1, const char* s2, size_t n) {
    if(n == 0) {
        return 0;
    }

    do {
        if(*s1 != *s2++) {
            return (*(unsigned char *)s1 - *(unsigned char *)--s2);
        }

        if(*s1++ == 0) {
            break;
        }
    } while(--n != 0);
    return 0;
}

size_t strlen(const char *str) {
    const char* end = str;
    
    for(; *end; ++end);
    return(end - str);
}

template<typename T>
static void* core_memset(T* dst, int val, size_t &len) {
    while(len >= sizeof(T)) {
        *dst++ = val;
        len   -= sizeof(T);
    }

    return dst;
}

static void* simple_memset(void* dest, int val, size_t len) {
    core_memset(static_cast<uint8_t*>(dest), val, len);
    return dest;
}

static void* cplx_memset(void* dst, int val, size_t len) {
    void*const org_dst = dst;

    if(reinterpret_cast<uintptr_t>(dst) & 0x2 == 0) {
        dst = core_memset(static_cast<uint32_t*>(dst), val, len);    
    }

    if(reinterpret_cast<uintptr_t>(dst) & 0x1 == 0) {
        dst = core_memset(static_cast<uint16_t*>(dst), val, len);
    }
    
    if(len > 0) {
        simple_memset(dst, val, len);
    }
    return org_dst;
}

extern "C" {
    void* memset(void* dest, int val, size_t len) {
        return simple_memset(dest, val, len);
    }
}