/* * microconf.h * * Copyright 2025 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301, USA. * * */ #if (!defined(__LIB_MICROCONF_PARSER)) #define __LIB_MICROCONF_PARSER #define bool char #define true 1 #define is_space_test(x) (x <= 32 && x >= 0) #define false 0 #define ulong unsigned long #include #include #include typedef FILE* file_t; typedef struct { size_t max_len_key; size_t max_len_val; ulong max_cnt; } config_info_t; typedef struct { char* key; char* value; } save_data_t; void _remove_spaces_end(char* str) { if (str != NULL) { long pos = strlen(str); if (pos == 0) return; pos --; while (pos != 0) { if (is_space_test(str[pos])) str[pos] = '\0'; else { if (str[pos + 1] != '\0') str[pos + 1] = '\0'; return; } pos --; } } } int _microconf_read_file(file_t fp, save_data_t (*input_handler) (ulong), size_t max_len, size_t max_len_val, ulong max_cnt) { int c; bool is_comment = false; bool is_space = true; bool read_key = false; bool read_val = false; bool read_val_spaces = true; bool print_warning = true; ulong num = 0; size_t key_addr = 0; size_t val_addr = 0; save_data_t sv = {NULL, NULL}; int old = '\0'; ulong str_num = 0; while ((c = getc(fp)) != EOF) { /* Разделитель - перенос строки ('\n') */ if (c == '\n') { is_comment = false; is_space = true; read_key = false; read_val = false; key_addr = 0; val_addr = 0; read_val_spaces = true; print_warning = true; str_num ++; } /* Считать комментарием все до конца строки */ if (c == '#') is_comment = true; /* Если символ не входит в комментарий, то: */ if (!is_comment) { /* Пропустить пробелы в начале и конце строки */ if (is_space && !is_space_test(c)) { is_space = false; read_key = true; if (num == max_cnt) { puts("\033[1mmicroconf: \033[91mError: The memory is full!\033[0m Code: READ_COUNT_ERR"); return EXIT_FAILURE; } _remove_spaces_end(sv.key); _remove_spaces_end(sv.value); sv = input_handler(num); num ++; key_addr = 0; val_addr = 0; } } /* Чтение значения */ if (read_val) { if (read_val_spaces && !is_space_test(c)) read_val_spaces = false; if (!read_val_spaces) { if (c == '\n' || c == '#' || c == EOF) { val_addr --; sv.value[val_addr] = '\0'; read_val = false; } if (read_val) { if (sv.value != NULL) { sv.value[val_addr] = c; } val_addr ++; if (val_addr >= max_len_val && print_warning) { puts("\033[1mmicroconf: \033[35mWarning: The memory is full!\033[0m Code: READ_VAL_ERR"); val_addr --; print_warning = false; } } } } /* Чтение ключа */ if (read_key) { if (c == ':' && old == ':') { key_addr --; sv.key[key_addr] = '\0'; read_key = false; read_val = true; val_addr = 0; } if (read_key) { if (sv.key != NULL) { sv.key[key_addr] = c; } key_addr ++; if (key_addr >= max_len && print_warning) { puts("\033[1mmicroconf: \033[35mWarning: The memory is full!\033[0m Code: READ_KEY_ERR"); key_addr --; print_warning = false; } } } /* Проверка синтаксиса файла */ if ((c == '\n' || c == '#' || c == EOF) && read_key) { printf("\033[1mmicroconf: \033[91mError: Syntax error on line %lu\033[0m\n", str_num); return EXIT_FAILURE; } /* Сохраняем старое значение в переменную */ old = c; } /* Удаляем пробелы в конце строки */ _remove_spaces_end(sv.key); _remove_spaces_end(sv.value); return EXIT_SUCCESS; } int microconf_compile(file_t fp, save_data_t (*input_handler) (ulong), config_info_t st) { if (fp == NULL) { puts("\033[1mmicroconf: \033[91mError: Unable to open file!\033[0m"); return EXIT_FAILURE; } rewind(fp); return _microconf_read_file(fp, input_handler, st.max_len_key, st.max_len_val, st.max_cnt); } #undef bool #undef ulong #undef true #undef false #undef is_space_test #endif