/* * 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 typedef FILE* file_t; typedef struct { char* key; char* value; } save_data_t; 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; 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; 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[91mThe memory is full!\033[0m Code: READ_COUNT_ERR"); return EXIT_FAILURE; } sv = input_handler(num); num ++; key_addr = 0; val_addr = 0; } } /* Чтение значения */ if (read_val) { 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 (key_addr >= max_len) { puts("\033[1mmicroconf: \033[91mThe memory is full!\033[0m Code: READ_VAL_ERR"); return EXIT_FAILURE; } } } /* Чтение ключа */ 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) { puts("\033[1mmicroconf: \033[91mThe memory is full!\033[0m Code: READ_KEY_ERR"); return EXIT_FAILURE; } } } /* Проверка синтаксиса файла */ if ((c == '\n' || c == '#' || c == EOF) && read_key) { printf("\033[1mmicroconf: \033[91mSyntax error on line %lu\033[0m\n", str_num); return EXIT_FAILURE; } /* Сохраняем старое значение в переменную */ old = c; } return EXIT_SUCCESS; } int microconf_compile(file_t fp, save_data_t (*input_handler) (ulong), size_t max_len, size_t max_len_val, ulong max_cnt) { if (fp == NULL) { puts("\033[1mmicroconf: \033[91mUnable to open file!\033[0m"); return EXIT_FAILURE; } rewind(fp); return _microconf_read_file(fp, input_handler, max_len, max_len_val, max_cnt); } #undef bool #undef ulong #undef true #undef false #undef is_space_test #endif