Files
Deshab-OS/CODE/UTSM/kernel/ini_parser.c
T

167 lines
4.4 KiB
C
Raw Normal View History

2026-07-31 13:53:49 +08:00
/* INI 分区格式解析器 — freestanding, 无堆分配, 无 libc 依赖 */
#include "ini_parser.h"
/* ---- 内部辅助 ---- */
static int ini_streq(const char *a, const char *b) {
if (!a || !b) return 0;
while (*a && *b) {
if (*a != *b) return 0;
a++; b++;
}
return *a == *b;
}
static int ini_isspace(char c) {
return c == ' ' || c == '\t' || c == '\r';
}
static int ini_isdigit(char c) {
return c >= '0' && c <= '9';
}
static int ini_strncpy(char *dst, const char *src, u32 max) {
u32 i = 0;
while (i + 1 < max && src[i]) {
dst[i] = src[i];
i++;
}
dst[i] = 0;
return (int)i;
}
static int ini_atoi(const char *s) {
int neg = 0, v = 0;
if (!s) return 0;
while (ini_isspace(*s)) s++;
if (*s == '-') { neg = 1; s++; }
while (ini_isdigit(*s)) {
v = v * 10 + (*s - '0');
s++;
}
return neg ? -v : v;
}
static int ini_parse_bool(const char *s) {
if (!s) return -1;
if (s[0] == '1') return 1;
if (s[0] == '0') return 0;
if (ini_streq(s, "true")) return 1;
if (ini_streq(s, "false")) return 0;
if (ini_streq(s, "yes")) return 1;
if (ini_streq(s, "no")) return 0;
return -1;
}
/* ---- 公共接口 ---- */
int ini_parse(const char *text, u32 size, ini_config *cfg) {
if (!text || !cfg) return -1;
cfg->count = 0;
char cur_section[32] = {0}; /* 当前分区名,默认空 */
u32 pos = 0;
while (pos < size) {
/* 跳过行首空白 */
while (pos < size && (text[pos] == ' ' || text[pos] == '\t'))
pos++;
if (pos >= size) break;
char c = text[pos];
/* 空行或换行 */
if (c == '\n') { pos++; continue; }
/* 注释行: # 或 ; 开头 */
if (c == '#' || c == ';') {
while (pos < size && text[pos] != '\n') pos++;
continue;
}
/* 分区头: [section] */
if (c == '[') {
pos++; /* 跳过 '[' */
u32 si = 0;
while (pos < size && text[pos] != ']' && text[pos] != '\n' && si + 1 < 32) {
cur_section[si++] = text[pos++];
}
cur_section[si] = 0;
/* 跳过到行尾 */
while (pos < size && text[pos] != '\n') pos++;
continue;
}
/* key=value 行 */
if (cfg->count >= 64) break; /* 达到上限 */
ini_entry *e = &cfg->entries[cfg->count];
/* 读取 key */
u32 ki = 0;
while (pos < size && text[pos] != '=' && text[pos] != '\n' &&
!ini_isspace(text[pos]) && ki + 1 < 32) {
e->key[ki++] = text[pos++];
}
e->key[ki] = 0;
/* 跳过 key 和 '=' 之间的空白 */
while (pos < size && ini_isspace(text[pos]) && text[pos] != '\n')
pos++;
/* 期望 '=' */
if (pos >= size || text[pos] != '=') {
/* 无效行,跳到行尾 */
while (pos < size && text[pos] != '\n') pos++;
continue;
}
pos++; /* 跳过 '=' */
/* 跳过 '=' 后的空白 */
while (pos < size && ini_isspace(text[pos]) && text[pos] != '\n')
pos++;
/* 读取 value(到行尾,去除尾部空白) */
u32 vi = 0;
while (pos < size && text[pos] != '\n' && vi + 1 < 64) {
e->value[vi++] = text[pos++];
}
/* 去除尾部空白 */
while (vi > 0 && ini_isspace(e->value[vi - 1])) vi--;
e->value[vi] = 0;
/* 复制 section 名 */
ini_strncpy(e->section, cur_section, 32);
cfg->count++;
}
return 0;
}
const char *ini_get(const ini_config *cfg, const char *section, const char *key) {
if (!cfg || !section || !key) return NULL;
for (u32 i = 0; i < cfg->count; i++) {
if (ini_streq(cfg->entries[i].section, section) &&
ini_streq(cfg->entries[i].key, key)) {
return cfg->entries[i].value;
}
}
return NULL;
}
int ini_get_int(const ini_config *cfg, const char *section, const char *key, int defval) {
const char *v = ini_get(cfg, section, key);
if (!v || v[0] == 0) return defval;
return ini_atoi(v);
}
int ini_get_bool(const ini_config *cfg, const char *section, const char *key, int defval) {
const char *v = ini_get(cfg, section, key);
if (!v || v[0] == 0) return defval;
int b = ini_parse_bool(v);
return (b >= 0) ? b : defval;
}