3 changed files with 380 additions and 0 deletions
@ -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 <rtthread.h> |
|||
#include <dfs_posix.h> |
|||
#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); |
|||
@ -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 <stdio.h> |
|||
#include <stdlib.h> |
|||
#include <string.h> |
|||
#include <ctype.h> |
|||
#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; |
|||
} |
|||
@ -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 <stdio.h> |
|||
#include <stdlib.h> |
|||
#include <string.h> |
|||
#include <ctype.h> |
|||
|
|||
#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_ */ |
|||
Loading…
Reference in new issue