- 论坛徽章:
- 0
|
我写的一个功能还算强大的ini解析库,c实现
/* Licensed to the EZ Software Foundation (EZSF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
*/
/**
* @file es_ini.h
* @brief ES Inifile Routines
*/
#include "es_ini.h"
#include "es_lib.h"
struct es_inifile_t
{
es_string_t *fname;
es_ini_sec_t *top;
es_string_t *mark;
es_int32_t flag; /* ES_INI_READ or ES_INI_WRITE */
es_bool_t updated; /* has updated */
};
struct es_ini_sec_t
{
es_string_t *name;
es_string_t *mark;
es_ini_key_t *keys;
es_ini_sec_t *next;
};
struct es_ini_key_t
{
es_string_t *name;
es_string_t *value;
es_string_t *mark;
es_ini_key_t *next;
};
static void ini_line_trim(es_string_t *line)
{
char *p;
int count = 0;
int str_len = strlen(line);
p = line + str_len - 1;
while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') {
*p = '\0';
p--;
count++;
}
p = line;
while (*p == ' ' || *p == '\t') {
p++;
count++;
}
if (p != line) {
memmove(line, p, str_len-count);
line[str_len-count] = '\0';
}
}
static void pfree_key(es_ini_key_t *key)
{
es_ini_key_t *ref_curr = key;
es_ini_key_t *ref_next = NULL;
if (!key)
return;
while (ref_curr) {
ref_next = ref_curr->next;
es_pfree(&ref_curr->name);
es_pfree(&ref_curr->value);
es_pfree(&ref_curr->mark);
es_pfree(&ref_curr);
ref_curr = ref_next;
}
}
static void pfree_sec(es_ini_sec_t *sec)
{
es_ini_sec_t *ref_curr = sec;
es_ini_sec_t *ref_next = NULL;
if (!sec)
return;
while (ref_curr) {
ref_next = ref_curr->next;
es_pfree(&ref_curr->name);
es_pfree(&ref_curr->mark);
if (ref_curr->keys) {
pfree_key(ref_curr->keys);
ref_curr->keys = NULL;
}
es_pfree(&ref_curr);
ref_curr = ref_next;
}
}
ES_DECLARE(es_status_t) es_inifile_open(es_inifile_t **ini,
const char *fname,
es_int32_t flag)
{
FILE *ini_file = NULL;
es_status_t rv;
es_ini_sec_t *curr_sec = NULL, *last_sec = NULL;
es_ini_key_t *curr_key = NULL, *last_key = NULL;
char *p = NULL;
char *end = NULL;
es_uint16_t buffer_size = 4096;
es_uint16_t read_pos = 0;
es_string_t *buffer = NULL;
(*ini) = (es_inifile_t *)es_pmalloc(sizeof(es_inifile_t));
if (!*ini)
return ENOMEM;
(*ini)->top = NULL;
(*ini)->mark = NULL;
(*ini)->flag = flag;
(*ini)->updated = FALSE;
(*ini)->fname = es_pstrdup(fname);
ini_file = fopen(fname, "r");
if ((!ini_file) && (flag == ES_INI_RDWR) && (errno == ENOENT)) {
return ES_SUCCESS;
}
else if (!ini_file) {
rv = errno;
goto free_all_return;
}
buffer = es_pmalloc(buffer_size);
while (!feof(ini_file)) {
errno = 0; //!!!;( if not set to 0 else errno = buffer_size - read_pos;
p = fgets(buffer + read_pos, buffer_size - read_pos, ini_file);
if (p == NULL && errno != 0) {
rv = errno;
goto free_all_return;
}
/* Check if we got all the line. */
if (p) {
if (!feof(ini_file)) {
end = strchr(buffer, '\n');
if (!end) {
read_pos = es_pdata_size(buffer) - 1;
buffer = es_prealloc(buffer, es_pdata_size(buffer) * 2);
continue;
}
}
}
read_pos = 0;
/* 去前后无效字符 */
ini_line_trim(buffer);
/* 空行则忽略 */
if (buffer[0] == 0)
continue;
if (buffer[0] == '#' || buffer[0] == ';') {
if (!(*ini)->top) {
/* 第一个section前面的说明信息 */
es_pstrcat(&(*ini)->mark, buffer);
es_pstrcat(&(*ini)->mark, "\n");
}
else if (curr_key) {
es_pstrcat(&curr_key->mark, buffer);
es_pstrcat(&curr_key->mark, "\n");
}
else if (curr_sec) {
es_pstrcat(&curr_sec->mark, buffer);
es_pstrcat(&curr_sec->mark, "\n");
}
else {
rv = -1;
goto free_all_return;
}
}
else if (buffer[0] == '[') {
end = strchr(buffer, ']');
if (!end) {
rv = -1;
goto free_all_return;
}
curr_sec = (es_ini_sec_t *)es_pcalloc(sizeof(es_ini_sec_t));;
curr_sec->keys = NULL;
es_pstrncpy(&curr_sec->name, buffer + 1, end - buffer - 1);
if (!(*ini)->top) {
(*ini)->top = curr_sec;
}
else {
last_sec->next = curr_sec;
}
last_sec = curr_sec;
curr_key = NULL;
/* [sec]后面还有'#' or ';' ? */
if ((end = strpbrk(end, "#;")) != 0) {
es_pstrcat(&curr_sec->mark, end);
es_pstrcat(&curr_sec->mark, "\n");
}
}
else {
/* "key = value" or "key" */
char *pEqual = NULL;
pEqual = strchr(buffer, '=');
/* 忽略无效的key */
if (!curr_sec || !pEqual)
continue;
curr_key = (es_ini_key_t *)es_pcalloc(sizeof(es_ini_key_t));
es_pstrncpy(&curr_key->name, buffer, pEqual - buffer);
ini_line_trim(curr_key->name);
if (!curr_sec->keys) {
curr_sec->keys = curr_key;
}
else {
last_key->next = curr_key;
}
last_key = curr_key;
/* 搜索'='后第一个有效字符是否为'"' */
p = pEqual + 1;
while (*p == ' ' || *p == '\t') {
p++;
}
if (*p == '"') {
end = strrchr(p + 1, '"');
if (end) {
es_pstrncpy(&curr_key->value, p + 1, end - p - 1);
/* 后面还有'#' or ';' ? */
if ((end = strpbrk(end, "#;")) != 0) {
es_pstrcat(&curr_key->mark, end);
es_pstrcat(&curr_key->mark, "\n");
}
}
else {
es_pstrcpy(&curr_key->value, p + 1);
}
}
else {
/* 后面有'#' or ';' ? */
if ((end = strpbrk(p, "#;")) != 0) {
es_pstrcat(&curr_key->mark, end);
es_pstrcat(&curr_key->mark, "\n");
}
es_pstrncpy(&curr_key->value, p, end - p);
ini_line_trim(curr_key->value);
}
}
} /* end of while() */
es_pfree(&buffer);
fclose(ini_file);
return ES_SUCCESS;
free_all_return:
if (ini_file) fclose(ini_file);
es_pfree(&buffer);
es_pfree(&(*ini)->fname);
es_pfree(&(*ini)->mark);
//free top
pfree_sec((*ini)->top);
es_pfree(ini);
return rv;
}
static es_status_t ini_update(FILE *file, es_inifile_t *ini)
{
es_status_t rv;
es_ini_sec_t *sec;
es_ini_key_t *key_;
/* header mark */
if (ini->mark) {
if ((rv = fputs(ini->mark, file)) < 0)
return rv;
if ((rv = fputs("\n", file)) < 0)
return rv;
}
/* section */
for (sec = es_ini_sec_first(ini); sec; sec = es_ini_sec_next(sec)) {
/* section name */
if ((rv = fputs("[", file)) < 0)
return rv;
if ((rv = fputs(sec->name, file)) < 0)
return rv;
if ((rv = fputs("]\n", file)) < 0)
return rv;
/*section mark*/
if (sec->mark) {
if ((rv = fputs(sec->mark, file)) < 0)
return rv;
}
/*key*/
for (key_ = es_ini_key_first(sec); key_; key_ = es_ini_key_next(key_)) {
/* key = value */
if ((rv = fputs(key_->name, file)) < 0)
return rv;
if ((rv = fputs(" = \"", file)) < 0)
return rv;
if ((rv = fputs(key_->value, file)) < 0)
return rv;
if ((rv = fputs("\"\n", file)) < 0)
return rv;
/* key mark */
if (key_->mark) {
if ((rv = fputs(key_->mark, file)) < 0)
return rv;
}
}
if ((rv = fputs("\n", file)) < 0)
return rv;
}
return ES_SUCCESS;
}
ES_DECLARE(es_status_t) es_inifile_close(es_inifile_t **ini)
{
es_inifile_t *theini = *ini;
FILE *ini_file = NULL;
es_status_t rv;
if (!theini)
return ES_SUCCESS;
if ((theini->flag == ES_INI_RDWR)
&& theini->updated) {
ini_file = fopen(theini->fname, "w+");
if (!ini_file) {
return errno;
}
if ((rv = ini_update(ini_file, theini)) != ES_SUCCESS) {
fclose(ini_file);
return rv;
}
if ((rv = fclose(ini_file)) != ES_SUCCESS)
return rv;
}
if (theini->top) {
pfree_sec(theini->top);
theini->top = NULL;
}
es_pfree(&theini->fname);
es_pfree(&theini->mark);
es_pfree(&theini);
*ini = NULL;
return ES_SUCCESS;
}
ES_DECLARE(es_ini_sec_t *) es_ini_sec_first(es_inifile_t *ini)
{
if (!ini)
return NULL;
else
return ini->top;
}
ES_DECLARE(es_ini_sec_t *) es_ini_sec_next(es_ini_sec_t *sec)
{
if (!sec)
return NULL;
else
return sec->next;
}
ES_DECLARE(es_string_t *) es_ini_sec_get_name(es_ini_sec_t *sec)
{
if (!sec)
return NULL;
else
return sec->name;
}
ES_DECLARE(es_string_t *) es_ini_sec_get_mark(es_ini_sec_t *sec)
{
if (!sec)
return NULL;
else
return sec->mark;
}
ES_DECLARE(es_ini_key_t *) es_ini_key_first(es_ini_sec_t *sec)
{
if (!sec)
return NULL;
else
return sec->keys;
}
ES_DECLARE(es_ini_key_t *) es_ini_key_next(es_ini_key_t *key)
{
if (!key)
return NULL;
else
return key->next;
}
ES_DECLARE(es_string_t *) es_ini_key_get_name(es_ini_key_t *key)
{
if (!key)
return NULL;
else
return key->name;
}
ES_DECLARE(es_string_t *) es_ini_key_get_value(es_ini_key_t *key)
{
if (!key)
return NULL;
else
return key->value;
}
ES_DECLARE(es_string_t *) es_ini_key_get_mark(es_ini_key_t *key)
{
if (!key)
return NULL;
else
return key->mark;
}
ES_DECLARE(es_ini_sec_t *) es_ini_get_section(es_inifile_t *ini,
const char *section,
es_int32_t idx_sec)
{
es_ini_sec_t *sec;
int count = 0;
if (!ini || !section || !*section)
return NULL;
for (sec = es_ini_sec_first(ini); sec; sec = es_ini_sec_next(sec)) {
if (strcmp(sec->name, section) == 0) {
count++;
}
if (idx_sec == count)
return sec;
}
return NULL;
}
ES_DECLARE(es_ini_key_t *) es_ini_get_key(es_ini_sec_t *sec,
const char *key,
es_int32_t idx_key)
{
es_ini_key_t *key_;
int count = 0;
if (!sec || !key || !*key)
return NULL;
for (key_ = es_ini_key_first(sec); key_; key_ = es_ini_key_next(key_)) {
if (strcmp(key_->name, key) == 0) {
count++;
}
if (idx_key == count)
return key_;
}
return NULL;
}
ES_DECLARE(es_string_t *) es_ini_read_string(es_inifile_t *ini,
const char *section,
const char *key,
char *def)
{
return es_ini_read_string2(ini, section, 1, key, 1, def);
}
ES_DECLARE(es_string_t *) es_ini_read_string2(es_inifile_t *ini,
const char *section,
es_int32_t idx_sec,
const char *key,
es_int32_t idx_key,
char *def)
{
es_ini_sec_t *sec_;
es_ini_key_t *key_;
if (!ini || !section || !*section || !key || !*key)
return NULL;
sec_ = es_ini_get_section(ini, section, idx_sec);
if (!sec_)
return def;
key_ = es_ini_get_key(sec_, key, idx_key);
if (!key_)
return def;
return es_ini_key_get_value(key_);
}
ES_DECLARE(es_ini_sec_t *) es_ini_add_sec(es_inifile_t *ini,
const char *section,
const char *mark)
{
es_ini_sec_t *sec;
if (!ini || !section || !*section)
return NULL;
sec = (es_ini_sec_t *)es_pcalloc(sizeof(es_ini_sec_t));
if (!sec)
return NULL;
sec->name = es_pstrdup(section);
if (mark)
sec->mark = es_pstrdup(mark);
sec->next = ini->top;
ini->top = sec;
ini->updated = TRUE;
return sec;
}
ES_DECLARE(es_ini_key_t *) es_ini_add_key(es_inifile_t *ini,
const char *section,
es_int32_t idx_sec,
const char *key,
const char *value,
const char *mark)
{
es_ini_sec_t *sec;
es_ini_key_t *key_;
if (!ini || !section || !*section || !key || !*key)
return NULL;
sec = es_ini_get_section(ini, section, idx_sec);
if (!sec) {
sec = es_ini_add_sec(ini, section, NULL);
if (!sec)
return NULL;
}
key_ = (es_ini_key_t *)es_pcalloc(sizeof(es_ini_key_t));
if (!key_)
return NULL;
key_->name = es_pstrdup(key);
if (value)
key_->value = es_pstrdup(value);
if (mark)
key_->mark = es_pstrdup(mark);
key_->next = sec->keys;
sec->keys = key_;
ini->updated = TRUE;
return key_;
}
ES_DECLARE(void) es_ini_del_sec(es_inifile_t *ini,
const char *section)
{
es_ini_del_sec2(ini, section, 1);
}
ES_DECLARE(void) es_ini_del_sec2(es_inifile_t *ini,
const char *section,
es_int32_t idx_sec)
{
es_ini_sec_t *sec, *ref;
if (!ini || !section || !*section)
return;
sec = es_ini_get_section(ini, section, idx_sec);
if (!sec)
return;
if (ini->top == sec)
ini->top = sec->next;
else
for (ref = es_ini_sec_first(ini); ref; ref = es_ini_sec_next(ref)) {
if (ref->next == sec) {
ref->next = sec->next;
break;
}
}
sec->next = NULL;
pfree_sec(sec);
ini->updated = TRUE;
return;
}
ES_DECLARE(void) es_ini_del_key(es_inifile_t *ini,
const char *section,
const char *key)
{
es_ini_del_key2(ini, section, 1, key, 1);
}
ES_DECLARE(void) es_ini_del_key2(es_inifile_t *ini,
const char *section,
es_int32_t idx_sec,
const char *key,
es_int32_t idx_key)
{
es_ini_sec_t *sec;
es_ini_key_t *key_, *ref;
if (!ini || !section || !*section || !key || !*key)
return;
sec = es_ini_get_section(ini, section, idx_sec);
if (!sec)
return;
key_ = es_ini_get_key(sec, key, idx_key);
if (!key_)
return;
if (sec->keys == key_)
sec->keys = key_->next;
else
for (ref = es_ini_key_first(sec); ref; ref = es_ini_key_next(ref)) {
if (ref->next == key_) {
ref->next = key_->next;
break;
}
}
key_->next = NULL;
pfree_key(key_);
ini->updated = TRUE;
return;
}
ES_DECLARE(es_bool_t) es_ini_upd_key(es_inifile_t *ini,
const char *section,
const char *key,
const char *value)
{
return es_ini_upd_key2(ini, section, 1, key, 1, value);
}
ES_DECLARE(es_bool_t) es_ini_upd_key2(es_inifile_t *ini,
const char *section,
es_int32_t idx_sec,
const char *key,
es_int32_t idx_key,
const char *value)
{
es_ini_sec_t *sec;
es_ini_key_t *key_;
if (!ini || !section || !*section || !key || !*key)
return FALSE;
sec = es_ini_get_section(ini, section, idx_sec);
if (!sec)
return FALSE;
key_ = es_ini_get_key(sec, key, idx_key);
if (!key_)
return FALSE;
if (value) {
es_pstrcpy(&key_->value, value);
}
else
es_pstrcpy(&key_->value, "");
ini->updated = TRUE;
return TRUE;
}
可以支持解析如下的示例.ini文件
#lllllllllllllllllllll
;llllllllllllllllllllll
#lllllllllllllllllll
[sec_one]
# 222222222222222222222
;22223333333333
key1 = " " 334455 # "
#######################################
#3333333333333344444444444444444444444444
#key11111111111111111111111111111111
key1 = "rrrrrrrrrrrrrrrrrrrrrrrr444444444444444444444444444444"
key2 = "wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww4"
;key2wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
[sec_two]
# 222222222222222222222
;22223333333333
key1111 = "334455"
#3333333333333344444444444444444444444444
#key11111111111111111111111111111111
key1111 = "rrrrrrrrrrrrrrrrrrrrrrrr44444444444444444"
key22222 = "wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww4"
;key2wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
ABC = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaAAA"
AA"
[sec_one]
key=kkk
key=111
还支持改写.ini文件。 |
评分
-
查看全部评分
|