FUCKYOU
This commit is contained in:
@@ -0,0 +1,166 @@
|
||||
/* 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;
|
||||
}
|
||||
Reference in New Issue
Block a user