diff --git a/applications/INI/config.c b/applications/INI/config.c new file mode 100644 index 0000000..5a24bac --- /dev/null +++ b/applications/INI/config.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2025-12-01 Administrator the first version + */ +#include +#include +#include "ini.h" +#include "Variable.h" + +#define INI_config "/sys/828config.ini" + +int read_write_sample(void) +{ + //检查文件 + if (access(INI_config, F_OK) != 0) + { + int fd = open(INI_config, O_WRONLY | O_CREAT);//创建文件 + close(fd); + } + // 初始化INI解析器 + INI_File *ini = ini_init(); + if (!ini) { + rt_kprintf("1\n"); + return -1; + } + // 解析INI文件 + if (ini_parse(ini, INI_config) != 0) { + rt_kprintf("2\n"); + ini_free(ini); + return -1; + } + // 读取各种类型的值 + strncpy(machine_ID, ini_get_value(ini, "CONFIG", "ID"),sizeof(machine_ID)); + machine_name = ini_get_value(ini, "CONFIG", "NAME"); + + //// ini_set_value(ini,"database", "host","192.168.9.1"); + + // ini_save(ini,INI_config); + + // 清理资源 + ini_free(ini); + return 0; +} + +INIT_APP_EXPORT(read_write_sample); diff --git a/applications/INI/ini.c b/applications/INI/ini.c new file mode 100644 index 0000000..6984942 --- /dev/null +++ b/applications/INI/ini.c @@ -0,0 +1,278 @@ +/** + * Copyright (c) 2016 rxi + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include +#include +#include +#include +#include "ini.h" + +// 去除字符串首尾的空白字符 +char* trim(char* str) { + char *end; + + // 去除首部空白 + while(isspace((unsigned char)*str)) str++; + + if(*str == 0) return str; + + // 去除尾部空白 + end = str + strlen(str) - 1; + while(end > str && isspace((unsigned char)*end)) end--; + + end[1] = '\0'; + return str; +} + +// 初始化INI文件结构 +INI_File* ini_init() { + INI_File *ini = malloc(sizeof(INI_File)); + if (!ini) return NULL; + + ini->section_capacity = 10; + ini->section_count = 0; + ini->sections = malloc(sizeof(INI_Section) * ini->section_capacity); + + return ini; +} + +// 释放INI文件结构 +void ini_free(INI_File *ini) { + if (!ini) return; + + for (int i = 0; i < ini->section_count; i++) { + free(ini->sections[i].entries); + } + free(ini->sections); + free(ini); +} + +// 解析INI文件 +int ini_parse(INI_File *ini, const char *filename) { + FILE *file = fopen(filename, "r"); + if (!file) { + return -1; // 文件打开失败 + } + + char line[MAX_LINE_LENGTH]; + char current_section[MAX_SECTION_LENGTH] = ""; + int line_num = 0; + + while (fgets(line, sizeof(line), file)) { + line_num++; + char *trimmed_line = trim(line); + + // 跳过空行和注释 + if (strlen(trimmed_line) == 0 || trimmed_line[0] == ';' || trimmed_line[0] == '#') { + continue; + } + + // 处理节(section) + if (trimmed_line[0] == '[' && trimmed_line[strlen(trimmed_line)-1] == ']') { + strncpy(current_section, trimmed_line + 1, strlen(trimmed_line) - 2); + current_section[strlen(trimmed_line) - 2] = '\0'; + trim(current_section); + continue; + } + + // 处理键值对 + char *equal_pos = strchr(trimmed_line, '='); + if (equal_pos) { + *equal_pos = '\0'; + char *key = trim(trimmed_line); + char *value = trim(equal_pos + 1); + + // 如果key或value为空,跳过 + if (strlen(key) == 0 || strlen(value) == 0) { + continue; + } + + // 添加到INI结构 + ini_set_value(ini, current_section, key, value); + } + } + + fclose(file); + return 0; +} + +// 设置键值对 +int ini_set_value(INI_File *ini, const char *section, const char *key, const char *value) { + // 查找或创建section + INI_Section *current_section = NULL; + for (int i = 0; i < ini->section_count; i++) { + if (strcmp(ini->sections[i].section, section) == 0) { + current_section = &ini->sections[i]; + break; + } + } + + // 如果section不存在,创建新的 + if (!current_section) { + if (ini->section_count >= ini->section_capacity) { + ini->section_capacity *= 2; + ini->sections = realloc(ini->sections, sizeof(INI_Section) * ini->section_capacity); + } + + current_section = &ini->sections[ini->section_count]; + strncpy(current_section->section, section, MAX_SECTION_LENGTH - 1); + current_section->section[MAX_SECTION_LENGTH - 1] = '\0'; + current_section->entry_capacity = 10; + current_section->entry_count = 0; + current_section->entries = malloc(sizeof(INI_Entry) * current_section->entry_capacity); + ini->section_count++; + } + + // 查找是否已存在该key + for (int i = 0; i < current_section->entry_count; i++) { + if (strcmp(current_section->entries[i].key, key) == 0) { + // 更新已存在的值 + strncpy(current_section->entries[i].value, value, MAX_VALUE_LENGTH - 1); + current_section->entries[i].value[MAX_VALUE_LENGTH - 1] = '\0'; + return 0; + } + } + + // 添加新的键值对 + if (current_section->entry_count >= current_section->entry_capacity) { + current_section->entry_capacity *= 2; + current_section->entries = realloc(current_section->entries, + sizeof(INI_Entry) * current_section->entry_capacity); + } + + INI_Entry *entry = ¤t_section->entries[current_section->entry_count]; + strncpy(entry->key, key, MAX_KEY_LENGTH - 1); + entry->key[MAX_KEY_LENGTH - 1] = '\0'; + strncpy(entry->value, value, MAX_VALUE_LENGTH - 1); + entry->value[MAX_VALUE_LENGTH - 1] = '\0'; + current_section->entry_count++; + + return 0; +} + +// 保存INI文件到磁盘 +int ini_save(INI_File *ini, const char *filename) { + FILE *file = fopen(filename, "w"); + if (!file) { + return -1; // 文件打开失败 + } + + // 首先处理空section(全局设置) + for (int i = 0; i < ini->section_count; i++) { + if (strlen(ini->sections[i].section) == 0) { + for (int j = 0; j < ini->sections[i].entry_count; j++) { + fprintf(file, "%s = %s\n", + ini->sections[i].entries[j].key, + ini->sections[i].entries[j].value); + } + if (ini->sections[i].entry_count > 0) { + fprintf(file, "\n"); // 在节之间添加空行 + } + break; + } + } + + // 处理其他section + for (int i = 0; i < ini->section_count; i++) { + if (strlen(ini->sections[i].section) > 0) { + // 写入section头 + fprintf(file, "[%s]\n", ini->sections[i].section); + + // 写入该section的所有键值对 + for (int j = 0; j < ini->sections[i].entry_count; j++) { + fprintf(file, "%s = %s\n", + ini->sections[i].entries[j].key, + ini->sections[i].entries[j].value); + } + fprintf(file, "\n"); // 在节之间添加空行 + } + } + + fclose(file); + return 0; +} + +// 删除指定的键 +int ini_delete_key(INI_File *ini, const char *section, const char *key) { + for (int i = 0; i < ini->section_count; i++) { + if (strcmp(ini->sections[i].section, section) == 0) { + for (int j = 0; j < ini->sections[i].entry_count; j++) { + if (strcmp(ini->sections[i].entries[j].key, key) == 0) { + // 将后面的元素前移 + for (int k = j; k < ini->sections[i].entry_count - 1; k++) { + memcpy(&ini->sections[i].entries[k], + &ini->sections[i].entries[k + 1], + sizeof(INI_Entry)); + } + ini->sections[i].entry_count--; + return 0; // 成功删除 + } + } + break; + } + } + return -1; // 未找到 +} +// 获取键值 +char* ini_get_value(INI_File *ini, const char *section, const char *key) { + for (int i = 0; i < ini->section_count; i++) { + if (strcmp(ini->sections[i].section, section) == 0) { + for (int j = 0; j < ini->sections[i].entry_count; j++) { + if (strcmp(ini->sections[i].entries[j].key, key) == 0) { + return ini->sections[i].entries[j].value; + } + } + break; + } + } + return NULL; // 未找到 +} + +// 获取整数值 +int ini_get_int(INI_File *ini, const char *section, const char *key, int default_value) { + const char *value = ini_get_value(ini, section, key); + if (!value) return default_value; + return atoi(value); +} + +// 获取浮点数值 +double ini_get_double(INI_File *ini, const char *section, const char *key, double default_value) { + const char *value = ini_get_value(ini, section, key); + if (!value) return default_value; + return atof(value); +} + +// 获取布尔值 +int ini_get_bool(INI_File *ini, const char *section, const char *key, int default_value) { + const char *value = ini_get_value(ini, section, key); + if (!value) return default_value; + + if (strcasecmp(value, "true") == 0 || strcasecmp(value, "yes") == 0 || + strcasecmp(value, "1") == 0 || strcasecmp(value, "on") == 0) { + return 1; + } + if (strcasecmp(value, "false") == 0 || strcasecmp(value, "no") == 0 || + strcasecmp(value, "0") == 0 || strcasecmp(value, "off") == 0) { + return 0; + } + + return default_value; +} diff --git a/applications/INI/ini.h b/applications/INI/ini.h new file mode 100644 index 0000000..8757a07 --- /dev/null +++ b/applications/INI/ini.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2025-12-01 Administrator the first version + */ +#ifndef APPLICATIONS_INI_INI_H_ +#define APPLICATIONS_INI_INI_H_ + +#include +#include +#include +#include + +#define MAX_LINE_LENGTH 256 +#define MAX_KEY_LENGTH 64 +#define MAX_VALUE_LENGTH 128 +#define MAX_SECTION_LENGTH 64 + +typedef struct { + char key[MAX_KEY_LENGTH]; + char value[MAX_VALUE_LENGTH]; +} INI_Entry; + +typedef struct { + char section[MAX_SECTION_LENGTH]; + INI_Entry *entries; + int entry_count; + int entry_capacity; +} INI_Section; + +typedef struct { + INI_Section *sections; + int section_count; + int section_capacity; +} INI_File; + +extern INI_File* ini_init(); +extern void ini_free(INI_File *ini); +extern int ini_parse(INI_File *ini, const char *filename); +extern int ini_set_value(INI_File *ini, const char *section, const char *key, const char *value); +extern int ini_save(INI_File *ini, const char *filename); +extern int ini_delete_key(INI_File *ini, const char *section, const char *key); +extern char* ini_get_value(INI_File *ini, const char *section, const char *key); +extern int ini_get_int(INI_File *ini, const char *section, const char *key, int default_value); +extern double ini_get_double(INI_File *ini, const char *section, const char *key, double default_value); +extern int ini_get_bool(INI_File *ini, const char *section, const char *key, int default_value); + +#endif /* APPLICATIONS_INI_INI_H_ */