381 lines
8.7 KiB
C
Executable File
381 lines
8.7 KiB
C
Executable File
#include <stdio.h>
|
|
#include <errno.h>
|
|
|
|
#include "param_config.h"
|
|
|
|
|
|
#ifdef DEBG_PARAM
|
|
#define PRINT_ERRMSG(STR) fprintf(stderr,"line:%d,msg:%s,eMsg:%s\n", __LINE__, STR, strerror(errno))
|
|
#else
|
|
#define PRINT_ERRMSG(STR) do{}while(0)
|
|
#endif
|
|
/**
|
|
* Check whether string is empty
|
|
**/
|
|
bool str_empty(const char *string)
|
|
{
|
|
return NULL == string || 0 == strlen(string);
|
|
}
|
|
|
|
/**
|
|
* add information to Linklist
|
|
**/
|
|
bool cnf_add_option(Config *cnf, const char *section, const char *key, const char *value)
|
|
{
|
|
if (NULL == cnf || str_empty(section) || str_empty(key) || str_empty(value)) {
|
|
return false;
|
|
}
|
|
|
|
Data *p,*q;
|
|
p = q = cnf->data; //check if the seciton exist
|
|
while (NULL != p && 0 != strcmp(p->section, section)) {
|
|
q = p;
|
|
p = p->next;
|
|
}
|
|
|
|
if (NULL == p) { /*Non-existent ,malloc the data Linklist*/
|
|
p = (Data*)malloc(sizeof(Data));
|
|
if (NULL == p) {
|
|
return false;
|
|
}
|
|
strcpy(p->section, section);
|
|
p->option = NULL; // the link of option must be NULL
|
|
p->next = NULL;
|
|
if(q==NULL)
|
|
cnf->data = p;
|
|
else
|
|
q ->next = p;
|
|
}
|
|
|
|
Option *m,*n;
|
|
m = n = p->option;
|
|
while (NULL != m && 0 != strcmp(m->key, key)) {
|
|
n=m;
|
|
m= m->next; /* check if the key exist*/
|
|
}
|
|
|
|
if (NULL == m) { /*Non-existent ,malloc the option Linklist*/
|
|
m = (Option*)malloc(sizeof(Option));
|
|
if (NULL == m) {
|
|
return false;
|
|
}
|
|
strcpy(m->key, key);
|
|
m->next = NULL;
|
|
if(n == NULL)
|
|
p->option = m;
|
|
else
|
|
n->next = m;
|
|
}
|
|
strcpy(m->value, value); // copy the value of option
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Remove all the blanks and annotations in the string
|
|
**/
|
|
bool strip_comments(char *string, char comment)
|
|
{
|
|
if (NULL == string || '\n' == *string || '\r' == *string) { // enter ,newline : empty line
|
|
return false;
|
|
}
|
|
|
|
char *p, *q; //Remove all the blanks and annotations
|
|
for (p = q = string; *p != '\0' && *p != comment; p++) {
|
|
if (0 == isspace(*p)) {
|
|
*q++ = *p;
|
|
}
|
|
}
|
|
*q = '\0';
|
|
|
|
return 0 != strlen(string); /* valid data length is not 0,return true*/
|
|
}
|
|
|
|
/**
|
|
* paser config file.
|
|
**/
|
|
Config *cnf_load_config(const char *filename)
|
|
{
|
|
Config *cnf = (Config*)malloc(sizeof(Config));
|
|
cnf->comment = '#'; //The character and following characters of each line will be discarded
|
|
cnf->separator = '='; // Used to separate Section and data
|
|
cnf->data = NULL;
|
|
cnf->num = 0;
|
|
|
|
if (str_empty(filename)) {
|
|
return NULL;
|
|
}
|
|
|
|
char *p, sLine[MAX_VALUE*2]; /* sLine: one line data */
|
|
char section[MAX_VALUE], key[MAX_VALUE], value[MAX_VALUE];
|
|
int off=0;
|
|
FILE *fp = fopen(filename, "r");
|
|
if(NULL == fp) {
|
|
PRINT_ERRMSG("fopen");
|
|
free(cnf);
|
|
return NULL;
|
|
}
|
|
|
|
while (NULL != fgets(sLine, MAX_VALUE, fp)) {
|
|
if (strip_comments(sLine, cnf->comment)) {
|
|
if ('[' == sLine[0] && ']' == sLine[strlen(sLine)-1]) {
|
|
memset(section, '\0', MAX_VALUE);
|
|
strncpy(section, sLine+1, strlen(sLine)-2);
|
|
off = strlen(sLine)-2;
|
|
cnf->num++;
|
|
}else if ('{' == sLine[0] && '}' == sLine[strlen(sLine)-1]) {
|
|
strncpy(section+off, (char *)'_', 1);
|
|
if((strlen(sLine)-5 == 1)||(strlen(sLine)-2 == 1))
|
|
strncpy(section+off+1, sLine+strlen(sLine)-2, 1);
|
|
else if(strlen(sLine)-5 == 2)
|
|
strncpy(section+off+1, sLine+strlen(sLine)-3, 2);
|
|
}
|
|
else if (NULL != (p = strchr(sLine, cnf->separator))) {
|
|
memset(key, '\0', MAX_VALUE);
|
|
strncpy(key, sLine, p - sLine);
|
|
strcpy(value, p + 1);
|
|
cnf_add_option(cnf, section, key, value); /* add information to linklist */
|
|
}
|
|
}
|
|
}
|
|
|
|
fclose(fp);
|
|
return cnf;
|
|
}
|
|
unsigned int cnf_get_total_num(Config *cnf)
|
|
{
|
|
if (NULL == cnf) {
|
|
PRINT_ERRMSG("cnf is NULL");
|
|
return false;
|
|
}
|
|
|
|
return cnf->num;
|
|
}
|
|
|
|
/**
|
|
* get value of the key under section.
|
|
**/
|
|
bool cnf_get_value(Config *cnf, const char *section, const char *key)
|
|
{
|
|
Data *p = cnf->data; /* check if have the section*/
|
|
while (NULL != p && 0 != strcmp(p->section, section)) {
|
|
p = p->next;
|
|
}
|
|
|
|
if (NULL == p) {
|
|
PRINT_ERRMSG("section not find!");
|
|
return false;
|
|
}
|
|
|
|
Option *q = p->option; /* check if have the key*/
|
|
while (NULL != q && 0 != strcmp(q->key, key)) {
|
|
q = q->next;
|
|
}
|
|
|
|
if (NULL == q) {
|
|
PRINT_ERRMSG("key not find!");
|
|
return false;
|
|
}
|
|
|
|
strcpy(cnf->re_string, q->value); /* get string*/
|
|
cnf->re_int = atoi(cnf->re_string); /* get int*/
|
|
cnf->re_bool = 0 == strcmp ("true", cnf->re_string); /* get bool*/
|
|
cnf->re_double = atof(cnf->re_string); /*get double*/
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* check if the seciton exist
|
|
**/
|
|
Data *cnf_has_section(Config *cnf, const char *section)
|
|
{
|
|
Data *p = cnf->data;
|
|
while (NULL != p && 0 != strcmp(p->section, section)) {
|
|
p = p->next;
|
|
}
|
|
|
|
if (NULL == p) {
|
|
return NULL;
|
|
}
|
|
|
|
return p;
|
|
}
|
|
|
|
/**
|
|
* check if the option under section exist
|
|
**/
|
|
Option *cnf_has_option(Config *cnf, const char *section, const char *key)
|
|
{
|
|
Data *p = cnf_has_section(cnf, section);
|
|
if (NULL == p) {
|
|
return NULL;
|
|
}
|
|
|
|
Option *q = p->option;
|
|
while (NULL != q && 0 != strcmp(q->key, key)) {
|
|
q = q->next;
|
|
}
|
|
if (NULL == q) {
|
|
return NULL;
|
|
}
|
|
|
|
return q;
|
|
}
|
|
|
|
/**
|
|
* print config information
|
|
**/
|
|
void print_config_info(Config *cnf)
|
|
{
|
|
Data *p = cnf->data;
|
|
while (NULL != p) {
|
|
printf("[%s]\n",p->section);
|
|
Option *q = p->option;
|
|
while (NULL != q) {
|
|
printf(" %s %c %s\n", q->key, cnf->separator, q->value);
|
|
q = q->next;
|
|
}
|
|
p = p->next;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* write config information to file
|
|
**/
|
|
bool cnf_write_file(Config *cnf, const char *filename, const char *header)
|
|
{
|
|
FILE *fp = fopen(filename, "w");
|
|
if(NULL == fp) {
|
|
PRINT_ERRMSG("fopen");
|
|
return false;
|
|
}
|
|
|
|
if (0 < strlen(header)) {
|
|
fprintf(fp, "%c %s\n\n", cnf->comment, header);
|
|
}
|
|
|
|
Option *q;
|
|
Data *p = cnf->data;
|
|
while (NULL != p) {
|
|
fprintf(fp, "[%s]\n", p->section);
|
|
q = p->option;
|
|
while (NULL != q) {
|
|
fprintf(fp, "\t %s %c %s\n", q->key, cnf->separator, q->value);
|
|
q = q->next;
|
|
}
|
|
p = p->next;
|
|
}
|
|
fclose(fp);
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* delete option
|
|
**/
|
|
bool cnf_remove_option(Config *cnf, const char *section, const char *key)
|
|
{
|
|
Data *ps = cnf_has_section(cnf, section);
|
|
if (NULL == ps) {
|
|
return NULL;
|
|
}
|
|
|
|
Option *p, *q;
|
|
q = p = ps->option;
|
|
while (NULL != p && 0 != strcmp(p->key, key)) {
|
|
if (p != q) {
|
|
q = q->next;
|
|
}
|
|
p = p->next;
|
|
}
|
|
|
|
if (NULL == p) {
|
|
return NULL;
|
|
}
|
|
|
|
if (p == q) { /* head node */
|
|
ps->option = p->next;
|
|
} else {
|
|
q->next = p->next;
|
|
}
|
|
|
|
free(p);
|
|
q = p = NULL;
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
*delete section
|
|
**/
|
|
bool cnf_remove_section(Config *cnf, const char *section)
|
|
{
|
|
if (str_empty(section)) {
|
|
return false;
|
|
}
|
|
|
|
Data *p, *q;
|
|
q = p = cnf->data;
|
|
while (NULL != p && 0 != strcmp(p->section, section)) {
|
|
if (p != q) { q = q->next; }
|
|
p = p->next;
|
|
}
|
|
|
|
if (NULL == p) {
|
|
return false;
|
|
}
|
|
|
|
if (p == q) { /* head node*/
|
|
cnf->data = p->next;
|
|
} else {
|
|
q->next = p->next;
|
|
}
|
|
|
|
Option *m,*n;
|
|
m = n = p->option;
|
|
while (NULL != m) {
|
|
n = m;
|
|
m = m->next;
|
|
free(n);
|
|
}
|
|
p->option = NULL;
|
|
free(p);
|
|
p = NULL;
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* release config section & option
|
|
**/
|
|
int cnf_release(Config *cnf)
|
|
{
|
|
int ret = 0;
|
|
if(cnf->data== NULL || cnf == NULL)
|
|
{
|
|
ret = -1;
|
|
printf("release error:%d from (handler == NULL)\n",ret);
|
|
return ret;
|
|
}
|
|
Data *p, *q;
|
|
Option *m,*n;
|
|
q = p = cnf->data;
|
|
m = n = p->option;
|
|
while(NULL != p){
|
|
m = n = p->option; //free option
|
|
while (NULL != n) {
|
|
m = n;
|
|
n = n->next;
|
|
free(m);
|
|
}
|
|
q=p; //free data
|
|
p=p->next;
|
|
free(q);
|
|
}
|
|
p=q=NULL;
|
|
m=n=NULL;
|
|
|
|
return ret;
|
|
}
|
|
|