commit 958645768939002b3d8f156f8b84b9ab907eb070 Author: german Date: Tue Dec 16 13:11:40 2025 +0400 Beta diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..f14a6a0 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,4 @@ +{ + "makefile.configureOnOpen": false, + "C_Cpp.errorSquiggles": "disabled" +} \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..def6eaa --- /dev/null +++ b/Makefile @@ -0,0 +1,45 @@ +# +# Makefile +# +# 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. +# +# + +CC=gcc +OPTIONS=-O2 -Wall -ansi +OUTPUT_NAME=microconf +COPY=cp +INPUT_NAME=example.c +REMOVE=rm +INSTALL_NAME=/usr/local/bin/microconf-example +MODE=chmod +x +RUN_OF=./ + +.PHONY: clear run install uninstall + +$(OUTPUT_NAME): $(INPUT_NAME) + $(CC) $(OPTIONS) $(INPUT_NAME) -o $(OUTPUT_NAME) +clear: + $(REMOVE) -f $(OUTPUT_NAME) +run: + $(MODE) $(OUTPUT_NAME) + $(RUN_OF)$(OUTPUT_NAME) +install: + $(COPY) $(OUTPUT_NAME) $(INSTALL_NAME) +uninstall: + $(REMOVE) $(INSTALL_NAME) diff --git a/README.md b/README.md new file mode 100644 index 0000000..975e031 --- /dev/null +++ b/README.md @@ -0,0 +1,11 @@ +# Microconf +Парсер формата конфигурации. +## Пример +Для компиляции примера используйте: +```bash +cd ~/microconf +make clear +make +./microconf``` +## Версия + - 1.0 - Бета diff --git a/example.c b/example.c new file mode 100644 index 0000000..133e181 --- /dev/null +++ b/example.c @@ -0,0 +1,85 @@ +/* + * example.c + * + * 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. + * + * + */ + + +#include "microconf.h" + +/* Настройки */ + +#define TEST_FILE "microconf_test.conf" +#define LEN_MAX_VAL 20 +#define LEN_MAX_KEY 10 +#define VALS_COUNT 3 + +/* Массивы */ + +char vals[VALS_COUNT][LEN_MAX_VAL] = {""}; +char keys[VALS_COUNT][LEN_MAX_KEY] = {""}; + +/* Готовый обработчик, требует только имена массивов */ + +#define INPUT_KEYS_NUM keys +#define INPUT_VALS_NUM vals + +#include "handler.h" + +/* + * + * Можно определить свой обработчик, например: + * + * save_data_t my_handler(unsigned long num) { + * save_data_t t; + * t.key = keys[num]; + * t.value = vals[num]; + * return t; + * } + * + */ + +int main(void) { + /* Отрыть файл */ + file_t fp = fopen(TEST_FILE, "r"); + /* Функция: + * int microconf_compile ( + * файловая_структура, + * обработчик_ввода, + * максимальная_длинна_ключа, + * максимальная_длинна_значения, + * максимальное_количество_ключей + * ); + */ + int status = microconf_compile(fp, microconf_std_handler, LEN_MAX_KEY, LEN_MAX_VAL, VALS_COUNT); + /* При ошибке - аварийно завершить */ + if (status == EXIT_FAILURE) return status; + /* Вывести в консоль */ + unsigned char num_read = 0; + while (num_read < 3) { + char* key = keys[num_read]; + char* val = vals[num_read]; + printf("Key=%s Value=%s\n", key, val); + num_read ++; + } + /* Закрытие файла и успешное завершение программы */ + fclose(fp); + return EXIT_SUCCESS; +} diff --git a/handler.h b/handler.h new file mode 100644 index 0000000..6f9600a --- /dev/null +++ b/handler.h @@ -0,0 +1,41 @@ +/* + * handler.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(__HANDLERS_H_FILE)) +#define __HANDLERS_H_FILE + +#include "microconf.h" + +#if (!defined(INPUT_KEYS_NUM)) || (!defined(INPUT_VALS_NUM)) +#error Please specify array names +#endif + +save_data_t microconf_std_handler(unsigned long num) { + save_data_t t; + t.key = INPUT_KEYS_NUM[num]; + t.value = INPUT_VALS_NUM[num]; + return t; +} + +#endif \ No newline at end of file diff --git a/microconf b/microconf new file mode 100755 index 0000000..5155765 Binary files /dev/null and b/microconf differ diff --git a/microconf.h b/microconf.h new file mode 100644 index 0000000..a1ca800 --- /dev/null +++ b/microconf.h @@ -0,0 +1,151 @@ +/* + * 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 diff --git a/microconf_test.conf b/microconf_test.conf new file mode 100644 index 0000000..d539a30 --- /dev/null +++ b/microconf_test.conf @@ -0,0 +1,25 @@ +# +# microconf_test.conf +# +# 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. +# +# + +key_1::value_1 # Value +key_2::value_2 # Value +key_3::value_3 # Value \ No newline at end of file