/*------------------------------------------------------------------------------
 *  Kintsugi OS KKLIBC source code
 *  File: kklibc/stdlib.h
 *  Title: Стандартный набор методов (заголовочный файл)
 *  Description: Заголовочный файл стандартной библиотеки Kintsugi OS.
 *               Определяет функции для работы со строками, памятью,
 *               преобразованиями и управления системой.
 * ---------------------------------------------------------------------------*/
#ifndef KKLIBC_STDLIB_H
#define KKLIBC_STDLIB_H

#include "ctypes.h"
#include "stdio.h"

/*******************************************************************************
 * Преобразования данных
 ******************************************************************************/

/**
 * @brief Конвертирует булеву переменную в строку "true" или "false".
 * @param value Булева переменная для конвертации.
 * @param str Указатель на буфер, куда будет записана результирующая строка.
 *            Буфер должен быть достаточно большим (минимум 6 символов для "false").
 */
void booltochar(u8 value, u8* str);

/**
 * @brief Преобразует целое число со знаком в строку в указанной системе счисления.
 * @param num Число для преобразования.
 * @param str Указатель на буфер для записи результата.
 * @param base Основание системы счисления (от 2 до 36).
 */
void itoa(int num, char* str, int base);

/**
 * @brief Преобразует целое число без знака в строку в указанной системе счисления.
 * @param num Число для преобразования.
 * @param str Указатель на буфер для записи результата.
 * @param base Основание системы счисления (от 2 до 36).
 */
void utoa(u32 num, char* str, int base);

/**
 * @brief (legacy, используйте itoa) Преобразует целое число в строку ASCII.
 * @param n Число для преобразования.
 * @param str Буфер для записи результата.
 */
void int_to_ascii(int n, char str[]);

/**
 * @brief (legacy, используйте itoa) Преобразует целое число в шестнадцатеричную строку ASCII.
 * @param n Число для преобразования.
 * @param str Буфер для записи результата.
 */
void hex_to_ascii(int n, char str[]);

/**
 * @brief Преобразует строку, представляющую число, в целое число со знаком.
 * @param str Указатель на строку для преобразования.
 * @return Результат преобразования.
 */
int strtoint(char* str);

/**
 * @brief Преобразует строку, представляющую шестнадцатеричное число, в целое число.
 * @param str Указатель на строку для преобразования (в формате "0xFF", "FF", etc.).
 * @return Результат преобразования.
 */
int hex_strtoint(char* str);

/*******************************************************************************
 * Работа со строками
 ******************************************************************************/

/**
 * @brief Вычисляет длину строки.
 * @param s Указатель на строку.
 * @return Длина строки (количество символов до завершающего нуля '\\0').
 */
int strlen(char s[]);

/**
 * @brief Копирует строку из src в dest.
 * @param dest Указатель на буфер назначения.
 * @param src Указатель на строку-источник.
 */
void strcpy(char* dest, char* src);

/**
 * @brief Копирует до n символов из строки src в dest.
 * @param dest Указатель на буфер назначения.
 * @param src Указатель на строку-источник.
 * @param n Максимальное количество символов для копирования.
 * @return Указатель на буфер назначения (dest).
 */
char* strncpy(char* dest, const char* src, unsigned int n);

/**
 * @brief Сравнивает две строки.
 * @param s1 Указатель на первую строку.
 * @param s2 Указатель на вторую строку.
 * @return 0 если строки равны, >0 если s1 > s2, <0 если s1 < s2.
 */
int strcmp(char s1[], char s2[]);

/**
 * @brief Сравнивает первые n символов двух строк.
 * @param s1 Указатель на первую строку.
 * @param s2 Указатель на вторую строку.
 * @param n Максимальное количество символов для сравнения.
 * @return 0 если части строк равны, >0 если s1 > s2, <0 если s1 < s2.
 */
int strncmp(const char* s1, const char* s2, unsigned int n);

/**
 * @brief Объединяет строку src к концу строки dest.
 * @param dest Указатель на целевую строку. Должна иметь достаточно места.
 * @param src Указатель на строку-источник.
 */
void append(char s[], char n);

/**
 * @brief Объединяет не более n символов строки src к концу строки dest.
 * @param dest Указатель на целевую строку. Должна иметь достаточно места.
 * @param src Указатель на строку-источник.
 * @param n Максимальное количество символов для добавления.
 * @return Указатель на целевую строку (dest).
 */
char* strncat(char* dest, const char* src, unsigned int n);

/**
 * @brief Удаляет последний символ из строки (симуляция backspace).
 * @param s Указатель на строку для модификации.
 */
void backspace(char s[]);

/**
 * @brief Разворачивает строку на месте.
 * @param s Указатель на строку для разворота.
 */
void reverse(char s[]);

/**
 * @brief Ищет первое вхождение символа в строке.
 * @param s Указатель на строку для поиска.
 * @param c Искомый символ (передается как int, но преобразуется в char).
 * @return Указатель на найденный символ в строке или NULL, если символ не найден.
 */
char* strchr(const char* s, int c);

/**
 * @brief Ищет первое вхождение подстроки needle в строке haystack.
 * @param haystack Указатель на строку, в которой выполняется поиск.
 * @param needle Указатель на искомую подстроку.
 * @return Указатель на начало найденной подстроки или NULL, если подстрока не найдена.
 */
char* strstr(const char* haystack, const char* needle);

/**
 * @brief Вычисляет длину начального сегмента строки str1, состоящего только из символов строки str2.
 * @param str1 Указатель на анализируемую строку.
 * @param str2 Указатель на строку, содержащую набор искомых символов.
 * @return Длина начального сегмента.
 */
u32 strspn(const u8* str1, const u8* str2);

/**
 * @brief Вычисляет длину начального сегмента строки str1, который не содержит ни одного символа из строки
 * str2.
 * @param str1 Указатель на анализируемую строку.
 * @param str2 Указатель на строку, содержащую набор запрещенных символов.
 * @return Длина начального сегмента.
 */
u32 strcspn(const u8* str1, const u8* str2);

/**
 * @brief Ищет в строке str1 первый символ, который совпадает с любым символом из строки str2.
 * @param str1 Указатель на строку для поиска.
 * @param str2 Указатель на строку с искомыми символами.
 * @return Указатель на найденный символ или NULL, если символ не найден.
 */
u8* strpbrk(const u8* str1, const u8* str2);

/**
 * @brief Разбивает строку на токены по разделителю.
 * @param src_str Строка для разбиения. При последующих вызовах передавайте NULL.
 * @param delim Строка, содержащая символы-разделители.
 * @return Указатель на следующий токен или NULL, если токенов больше нет.
 */
char* strtok(char* src_str, char* delim);

/**
 * @brief Проверяет, является ли символ разделителем.
 * @param c Проверяемый символ.
 * @param delim Строка с разделителями.
 * @return Ненулевое значение, если символ является разделителем, иначе 0.
 */
unsigned int is_delim(char c, char* delim);

/*******************************************************************************
 * Работа с памятью
 ******************************************************************************/

/**
 * @brief Копирует блок памяти из src в dest.
 * @param dest Указатель на назначение.
 * @param src Указатель на источник.
 * @param n Количество байт для копирования.
 * @return Указатель на назначение (dest).
 */
void* memcpy(void* dest, const void* src, unsigned int n);

/**
 * @brief Копирует n байт из source в dest. (Альтернатива memcpy)
 * @param source Указатель на источник.
 * @param dest Указатель на назначение.
 * @param nbytes Количество байт для копирования.
 */
void memory_copy(u8* source, u8* dest, int nbytes);

/**
 * @brief Заполняет блок памяти указанным значением.
 * @param s Указатель на начало блока памяти.
 * @param c Значение для заполнения (передается как int, но преобразуется в unsigned char).
 * @param n Количество байт для заполнения.
 * @return Указатель на начало блока памяти (s).
 */
void* memset(void* s, int c, unsigned int n);

/**
 * @brief Заполняет блок памяти указанным байт-значением.
 * @param dest Указатель на начало блока памяти.
 * @param val Значение для заполнения.
 * @param len Количество байт для заполнения.
 */
void memory_set(u8* dest, u8 val, u32 len);

/**
 * @brief Заполняет блок памяти указанным 32-битным значением.
 * @param dest Указатель на начало блока памяти (должен быть выровнен по границе 4 байта).
 * @param val Значение для заполнения.
 * @param len Количество 32-битных слов для заполнения.
 */
void u32memory_set(u32* dest, u32 val, u32 len);

/**
 * @brief Перемещает блок памяти из src в dest. Области могут перекрываться.
 * @param dest Указатель на назначение.
 * @param src Указатель на источник.
 * @param n Количество байт для копирования.
 * @return Указатель на назначение (dest).
 */
void* memmove(void* dest, const void* src, u32 n);

/**
 * @brief Сравнивает два блока памяти.
 * @param ptr1 Указатель на первый блок памяти.
 * @param ptr2 Указатель на второй блок памяти.
 * @param n Количество байт для сравнения.
 * @return 0 если блоки идентичны, >0 если ptr1 > ptr2, <0 если ptr1 < ptr2.
 */
int memcmp(const void* ptr1, const void* ptr2, u32 n);

/**
 * @brief Ищет первое вхождение символа в блоке памяти.
 * @param ptr Указатель на блок памяти для поиска.
 * @param c Искомый символ (передается как int, но преобразуется в unsigned char).
 * @param n Размер блока памяти в байтах.
 * @return Указатель на найденный символ или NULL, если символ не найден.
 */
void* memchr(const void* ptr, int c, u32 n);

/*******************************************************************************
 * Генерация псевдослучайных чисел
 ******************************************************************************/

/**
 * @brief Генерирует псевдослучайное число используя линейный конгруэнтный метод.
 * @param state Указатель на переменную состояния генератора.
 * @return Псевдослучайное число в диапазоне [0, UINT32_MAX].
 */
u32 rand(u32* state);

/**
 * @brief Генерирует псевдослучайное число в заданном диапазоне.
 * @param state Указатель на переменную состояния генератора.
 * @param min Нижняя граница диапазона (включительно).
 * @param max Верхняя граница диапазона (включительно).
 * @return Псевдослучайное число в диапазоне [min, max].
 */
u32 rand_range(u32* state, u32 min, u32 max);

/*******************************************************************************
 * Форматированный вывод в буфер
 ******************************************************************************/

/**
 * @brief Записывает форматированную строку в буфер.
 * @param buf Указатель на буфер для записи результата.
 * @param fmt Указатель на строку формата.
 * @param ... Аргументы, соответствующие спецификаторам в формате.
 * @return Количество символов, записанных в буфер (без учета завершающего нуля).
 */
int sprintf(char* buf, const char* fmt, ...);

/**
 * @brief Записывает форматированную строку в буфер с ограничением размера.
 * @param buf Указатель на буфер для записи результата.
 * @param size Максимальное количество символов для записи (включая завершающий ноль).
 * @param fmt Указатель на строку формата.
 * @param ... Аргументы, соответствующие спецификаторам в формате.
 * @return Количество символов, которые *были бы* записаны, если бы size был достаточным
 *         (без учета завершающего нуля). Если возвращаемое значение >= size,
 *         произошло усечение.
 */
int snprintf(char* buf, unsigned int size, const char* fmt, ...);

/**
 * @brief Записывает форматированную строку в буфер с ограничением размера для va_list.
 * @param buf Указатель на буфер для записи результата.
 * @param size Максимальное количество символов для записи (включая завершающий ноль).
 * @param fmt Указатель на строку формата.
 * @param args Аргументы типа va_list.
 * @param ... Аргументы, соответствующие спецификаторам в формате.
 * @return Количество символов, которые *были бы* записаны, если бы size был достаточным
 *         (без учета завершающего нуля). Если возвращаемое значение >= size,
 *         произошло усечение.
 */
int vsnprintf(char* buf, unsigned int size, const char* fmt, va_list args);

/*******************************************************************************
 * Управление системой
 ******************************************************************************/

/**
 * @brief Перезагружает систему.
 */
void reboot();

/**
 * @brief Приостанавливает выполнение на указанное количество миллисекунд.
 * @param ms Время задержки в миллисекундах.
 */
void wait(int ms);

#endif
