#include "string.h"

// Заполнить кусок памяти определенным байтом (очень нужно для очистки буферов)
void* memset(void* dest, int val, size_t count) {
    uint8_t* temp = (uint8_t*)dest;
    for (size_t i = 0; i < count; i++) {
        temp[i] = (uint8_t)val;
    }
    return dest;
}

// Скопировать кусок памяти (будем использовать для скроллинга VGA экрана)
void* memcpy(void* dest, const void* src, size_t count) {
    uint8_t* d = (uint8_t*)dest;
    const uint8_t* s = (const uint8_t*)src;
    for (size_t i = 0; i < count; i++) {
        d[i] = s[i];
    }
    return dest;
}

// Скопировать кусок памяти с учетом возможного пересечения областей
void* memmove(void* dest, const void* src, size_t count) {
    uint8_t* d = (uint8_t*)dest;
    const uint8_t* s = (const uint8_t*)src;
    
    if (d < s) {
        for (size_t i = 0; i < count; i++) {
            d[i] = s[i];
        }
    } else {
        for (size_t i = count; i > 0; i--) {
            d[i - 1] = s[i - 1];
        }
    }
    return dest;
}

// Сравнение блоков памяти
int memcmp(const void* s1, const void* s2, size_t count) {
    const uint8_t* p1 = (const uint8_t*)s1;
    const uint8_t* p2 = (const uint8_t*)s2;
    for (size_t i = 0; i < count; i++) {
        if (p1[i] != p2[i]) {
            return p1[i] - p2[i];
        }
    }
    return 0;
}

// Длина строки
size_t strlen(const char* str) {
    size_t len = 0;
    while (str[len] != '\0') {
        len++;
    }
    return len;
}

// Копирование строки
char* strcpy(char* dest, const char* src) {
    size_t i = 0;
    while ((dest[i] = src[i]) != '\0') {
        i++;
    }
    return dest;
}

// Конкатенация строк
char* strcat(char* dest, const char* src) {
    size_t dest_len = strlen(dest);
    size_t i = 0;
    while ((dest[dest_len + i] = src[i]) != '\0') {
        i++;
    }
    return dest;
}

// Сравнение строк (понадобится, когда будем парсить команды в терминале)
int strcmp(const char* s1, const char* s2) {
    while (*s1 && (*s1 == *s2)) {
        s1++;
        s2++;
    }
    return *(const unsigned char*)s1 - *(const unsigned char*)s2;
}

// Строка в число
int atoi(const char* str) {
    int res = 0;
    int sign = 1;
    int i = 0;

    // Пропускаем пробелы, если они есть
    while (str[i] == ' ' || str[i] == '\t') {
        i++;
    }

    // Учитываем знак
    if (str[i] == '-') {
        sign = -1;
        i++;
    } else if (str[i] == '+') {
        i++;
    }

    // Считаем само число
    while (str[i] >= '0' && str[i] <= '9') {
        res = res * 10 + (str[i] - '0');
        i++;
    }

    return sign * res;
}

// Число в строку (поддерживает base = 10 и base = 2)
char* itoa(int value, char* str, int base) {
    int i = 0;
    
    // Используем unsigned, чтобы безопасно обрабатывать MIN_INT
    unsigned int n;
    int is_negative = 0;

    if (base < 2 || base > 36) { str[0] = '\0'; return str; }

    if (value < 0 && base == 10) {
        is_negative = 1;
        n = (unsigned int)(-value); // Приводим к unsigned перед инверсией
    } else {
        n = (unsigned int)value;
    }

    if (n == 0) {
        str[i++] = '0';
        str[i] = '\0';
        return str;
    }

    while (n != 0) {
        int rem = n % base;
        str[i++] = (rem > 9) ? (rem - 10) + 'a' : rem + '0';
        n /= base;
    }

    if (is_negative) str[i++] = '-';
    str[i] = '\0';

    // Разворот (этот кусок у тебя верный)
    int start = 0, end = i - 1;
    while (start < end) {
        char temp = str[start];
        str[start] = str[end];
        str[end] = temp;
        start++; end--;
    }
    return str;
}

// Число в красивый Hex вид (например, 255 -> "0x000000ff")
char* itox(uint32_t value, char* str) {
    char* hex_digits = "0123456789abcdef";
    
    str[0] = '0';
    str[1] = 'x';
    str[10] = '\0'; // 2 символа на "0x" + 8 символов на 32-битное число
    
    // Заполняем с конца
    for (int i = 9; i >= 2; i--) {
        str[i] = hex_digits[value & 0xF];
        value >>= 4;
    }
    
    return str;
}
