/*------------------------------------------------------------------------------
 *  Kintsugi OS KKLIBC source code
 *  File: kklibc/ctypes.c
 *  Title: Библиотека для работы с типами C
 *	Description: null
 * ----------------------------------------------------------------------------*/

#include "ctypes.h"

#include "stdlib.h"

void panic_assert(const char* file, u32 line, const char* desc) {
    char buffer[256];
    snprintf(buffer, sizeof(buffer), "Assertion failed: %s, file %s, line %d", desc, file, line);
    panic_red_screen("Kernel Panic", buffer);
}

/**
 * @brief Классификация буквенно-цифровых символов
 *
 * Функция isalnum проверяет, является ли символ алфавитным или цифровым
 * в соответствии с функциями isalpha или isdigit.
 */
int isalnum(int c) {
    return isdigit(c) || isalpha(c);
}

/**
 * @brief Классификация алфавитных символов
 *
 * Функция isalpha проверяет, является ли символ буквой верхнего или нижнего регистра,
 * или одним из локале-зависимого набора алфавитных символов, для которых
 * iscntrl, isdigit, ispunct и isspace возвращают ложь. В локали "C"
 * isalpha возвращает истину только для символов, определяемых isupper или islower.
 */
int isalpha(int c) {
    return isupper(c) || islower(c);
}

/**
 * @brief Классизация пробельных символов
 *
 * Функция isblank проверяет, является ли символ стандартным пробельным символом
 * или одним из локале-зависимого набора символов, для которых isspace возвращает истину
 * и которые используются для разделения слов в строке текста. Стандартные пробельные
 * символы: пробел (' ') и горизонтальная табуляция ('\t'). В локали "C"
 * isblank возвращает истину только для стандартных пробельных символов.
 */
int isblank(int c) {
    return ((c == '\t') || (c == ' '));
}

/**
 * @brief Классификация управляющих символов
 *
 * Функция iscntrl проверяет, является ли символ управляющим.
 */
int iscntrl(int c) {
    return ((c <= 0x1F) || (c == 0x7F));
}

/**
 * @brief Классификация цифровых символов
 *
 * Функция isdigit проверяет, является ли символ цифрой (в соответствии с разделом 5.2.1).
 */
int isdigit(int c) {
    return ((c >= '0') && (c <= '9'));
}

/**
 * @brief Классификация видимых печатных символов
 *
 * Функция isgraph проверяет любой печатный символ, кроме пробела (' ').
 */
int isgraph(int c) {
    return ((c >= '!') && (c <= '~'));
}

/**
 * @brief Классификация символов нижнего регистра
 *
 * Функция islower проверяет, является ли символ буквой нижнего регистра
 * или одним из локале-зависимого набора символов, для которых iscntrl,
 * isdigit, ispunct и isspace возвращают ложь. В локали "C" islower возвращает
 * истину только для символов нижнего регистра (как определено в 5.2.1).
 */
int islower(int c) {
    return ((c >= 'a') && (c <= 'z'));
}

/**
 * @brief Классификация печатных символов
 *
 * Функция isprint проверяет любой печатный символ, включая пробел (' ').
 */
int isprint(int c) {
    return ((c >= ' ') && (c <= '~'));
}

/**
 * @brief Классификация знаков пунктуации
 *
 * Функция ispunct проверяет любой печатный символ, являющийся знаком пунктуации
 * (не пробельным и не буквенно-цифровым символом). В локали "C" ispunct возвращает
 * истину для всех печатных символов, для которых isspace и isalnum возвращают ложь.
 */
int ispunct(int c) {
    return (((c >= '!') && (c <= '/')) || ((c >= ':') && (c <= '@')) || ((c >= '[') && (c <= '`'))
            || ((c >= '{') && (c <= '~')));
}

/**
 * @brief Классификация пробельных символов
 *
 * Функция isspace проверяет, является ли символ стандартным пробельным символом
 * или одним из локале-зависимого набора символов, для которых isalnum возвращает ложь.
 * Стандартные пробельные символы: пробел (' '), перевод страницы ('\f'),
 * новая строка ('\n'), возврат каретки ('\r'), горизонтальная табуляция ('\t')
 * и вертикальная табуляция ('\v'). В локали "C" isspace возвращает истину только
 * для стандартных пробельных символов.
 */
int isspace(int c) {
    return (((c >= '\t') && (c <= '\r')) || (c == ' '));
}

/**
 * @brief Классификация символов верхнего регистра
 *
 * Функция isupper проверяет, является ли символ буквой верхнего регистра
 * или одним из локале-зависимого набора символов, для которых iscntrl,
 * isdigit, ispunct и isspace возвращают ложь. В локали "C" isupper возвращает
 * истину только для символов верхнего регистра (как определено в 5.2.1).
 */
int isupper(int c) {
    return ((c >= 'A') && (c <= 'Z'));
}

/**
 * @brief Классификация шестнадцатеричных цифр
 *
 * Функция isxdigit проверяет, является ли символ шестнадцатеричной цифрой
 * (в соответствии с разделом 6.4.4.1).
 */
int isxdigit(int c) {
    return (isdigit(c) || ((c >= 'A') && (c <= 'F')) || ((c >= 'a') && (c <= 'f')));
}

/**
 * @brief Преобразование символа в нижний регистр
 *
 * Функция tolower преобразует символ верхнего регистра в соответствующий
 * символ нижнего регистра.
 *
 * @return Если символ является буквой верхнего регистра и существует один или более
 *         соответствующих символов нижнего регистра (в соответствии с текущей локалью),
 *         возвращает соответствующий символ (всегда один и тот же для данной локали).
 *         В противном случае возвращается неизмененный аргумент.
 */
int tolower(int c) {
    return isupper(c) ? (c + 32) : c;
}

/**
 * @brief Преобразование символа в верхний регистр
 *
 * Функция toupper преобразует символ нижнего регистра в соответствующий
 * символ верхнего регистра.
 *
 * @return Если символ является буквой нижнего регистра и существует один или более
 *         соответствующих символов верхнего регистра (в соответствии с текущей локалью),
 *         возвращает соответствующий символ (всегда один и тот же для данной локали).
 *         В противном случае возвращается неизмененный аргумент.
 */
int toupper(int c) {
    return islower(c) ? (c - 32) : c;
}
