您的位置:首页 > 其它

通用配置文件生成类

2012-08-24 18:37 260 查看
//config.h
/*
此为一个通用配置文件生成类
主要是为了解决配置文件的生成,配置文件的读,配置文件的修改

此类的功能:
给定配置文件,则自动分析配置文件,并以字符串数组的形式返回;
以键值形式赋值
可以给定一个结构体数组,可以单个给定键值
格式如下

**************************************************
#配置文件总体说明
#

#键值1说明
key1=value1

#键值2说明
key2=value2

......
......
***************************************************
*爱锦
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifndef True
#define True 1
#define False 0
#endif

#ifndef KEY_VALUE
#define KEY_VALUE

#define MAX_KEY 128
#define MAX_VALUE 1024
#define MAX_PATH MAX_KEY
#define MAX_DESCRIPTION  2 * MAX_VALUE

typedef struct key_value {
char key[MAX_KEY];
char value[MAX_VALUE];
char description[MAX_DESCRIPTION];
int level;/*not used*/
/*
level is used as
[info]
...
...

[name]
...
...

but here i didn't want to use it
*/
struct key_value *next;
}Key_Value;
#endif

#ifndef config_file
#define config_file
typedef struct p {
char path[MAX_PATH];
int changed;
char description[MAX_DESCRIPTION];
Key_Value *head;
int len;
}Properties;
#endif

#ifndef Config_State
#define Config_State
enum F_ACCESS{S_N=0,S_R=1,S_W=2,S_RW=4};
#endif

class Config {
public :
Config(const char *path, const char *description=NULL);
Config(const char *path, const Key_Value *kv, int len, const char *description = NULL);
~Config();

//set or get the configs
//set
int setDescription(const char *description);
int setDescription(const char *key, const char *description);
int setProperty(const char *key, const char *value);
int setPropertys(const Key_Value *kv, int len);
void remove(const char *key);

//get
int getDescription(char *description);
int getDescription(const char *key, char *description);
int getProperty(const char *key, char *value);
int getPropertys(Key_Value *kv, int len);
//others
void clear();
F_ACCESS rwable();

protected:
Properties *properties;
void init();
//deals with file I\O
void import();
void copy(char *dest, const char *source, int m_size);
Key_Value *index(const char *key, int flag=0);
void write();
};

//config.cpp
#include "config.h"
#include <unistd.h>

Config::Config(const char *path, const char *description) {
properties = new Properties;
copy(properties->path,path, MAX_PATH);
if(description == NULL)
properties->description[0] = 0;
else
copy(properties->description, description, MAX_DESCRIPTION);
properties->changed = 0;
properties->len = 0;
init();
import();
}

Config::Config(const char *path, const Key_Value *kv, int len, const char *description) {
properties = new Properties;
copy(properties->path, path, MAX_PATH);
if(description == NULL)
properties->description[0] = 0;
else
copy(properties->description, description, MAX_DESCRIPTION);
properties->changed = False;
properties->len = 0;
init();
setPropertys(kv, len);
properties->changed = 1;
}

Config::~Config() {
if(properties->changed == 1) {
write();
}
if(properties->description[0] != 0) {
putchar('#');
for(int i = 0;i < strlen(properties->description); i ++) {
putchar(properties->description[i]);
if(properties->description[i] == 10)
putchar('#');
}
putchar(10);
putchar(10);
}
Key_Value *tmp = properties->head->next;
for (int i = 0;i < properties->len && tmp; i++) {
if(tmp->description[0] != 0) {
putchar('#');
for(int j = 0;j < strlen(tmp->description); j ++) {
putchar(tmp->description[j]);
if(tmp->description[j] == 10)
putchar('#');
}
putchar(10);
}
printf("%s=\"%s\" ", tmp->key, tmp->value);
if(tmp->value[strlen(tmp->value) - 1]  != '\n')
putchar(10);
tmp = tmp->next;
putchar(10);
}
}

int Config::setDescription(const char *description) {
if(description == NULL)
return False;
copy(properties->description, description, MAX_DESCRIPTION);
properties->changed = 1;
return True;
}

int Config::setDescription(const char *key, const char *description) {
if(key == NULL || description == NULL)
return False;
Key_Value *tmp = index(key);
if(tmp != NULL) {
copy(tmp->description, description, MAX_DESCRIPTION);
properties->changed = 1;
return True;
}
return False;
}

int Config::setProperty(const char *key, const char *value) {
if(key == NULL || value == NULL)
return False;
Key_Value *tmp = index(key);
if(tmp == NULL) {
tmp = new Key_Value;
copy(tmp->key, key, MAX_KEY);
copy(tmp->value, value, MAX_VALUE);
tmp->description[0] = 0;
tmp->level = 0;
tmp->next = properties->head->next;
properties->head->next = tmp;
properties->len ++;
}
else {
copy(tmp->value, value, MAX_VALUE);
}
properties->changed = 1;
return True;
}

int Config::setPropertys(const Key_Value *kv, int len) {
if(kv == NULL)
return False;
Key_Value *tmp;
for(int i = 0;i < len;i ++) {
tmp = index(kv[i].key);
if(tmp == NULL) {
tmp = new Key_Value;
copy(tmp->key,kv[i].key,MAX_KEY);
tmp->level = 0;
tmp->next = properties->head->next;
properties->head->next = tmp;
properties->len ++;
}
copy(tmp->value, kv[i].value, MAX_VALUE);
copy(tmp->description, kv[i].description,MAX_DESCRIPTION);
}
properties->changed = 1;
return True;
}

void Config::remove(const char *key) {
if(key == NULL)
return;
Key_Value *previous,*tmp;
previous = index(key, 1);
if(previous != NULL) {
tmp = previous->next;
previous->next = tmp->next;
delete tmp;
}
properties->changed = 1;
}

int Config::getDescription(char *description) {
if(description != NULL)
copy(description, properties->description, MAX_DESCRIPTION);
return True;
}

int Config::getDescription(const char *key, char *description) {
if(key == NULL || description == NULL)
return False;
Key_Value *tmp  = index(key, 0);
if(tmp != NULL) {
copy(description, tmp->description, MAX_DESCRIPTION);
return True;
}
return False;
}

int Config::getProperty(const char *key, char *value) {
if(key == NULL || value == NULL)
return False;
Key_Value *tmp  = index(key, 0);
if(tmp != NULL) {
copy(value, tmp->value, MAX_VALUE);
return True;
}
return False;
}

int Config::getPropertys(Key_Value *kv, int len) {
if(kv == NULL || len > properties->len)
return 0;
Key_Value  *next = properties->head->next;
for(int i = 0;i < properties->len && next;i ++) {
copy(kv[i].key,next->key,MAX_KEY);
copy(kv[i].value, next->value, MAX_VALUE);
next = next->next;
}
return properties->len;
}

void Config::clear() {
Key_Value *next = properties->head->next;
while(next) {
properties->head->next = next->next;
delete next;
next = properties->head->next;
}
properties->description[0] = 0;
properties->changed = 1;
properties->len = 0;
}

F_ACCESS Config::rwable() {
if(properties->path == NULL)
return S_N;
if(access(properties->path, R_OK | W_OK) == 0)
return S_RW;
else if(access(properties->path, R_OK) == 0)
return S_R;
else if(access(properties->path, W_OK) == 0)
return S_W;
return S_N;
}

//int Config::touch(const char *path,int access) {}

void Config::init() {
//init head
properties->head = new Key_Value;
properties->head->level = 0;
properties->head->next = NULL;
}

void Config::import() {
if(rwable() != S_R && rwable() != S_RW)
return ;
FILE *f = fopen(properties->path, "r");
char str[MAX_DESCRIPTION];
Key_Value *tmp, *last = properties->head;
// char *delim = "=";
if(fgets(str,MAX_DESCRIPTION, f ) == NULL)
goto END;

//must have global descripton
while(str[0] == '#') {
sprintf(properties->description + strlen(properties->description) , "%s", str + 2);
if(fgets(str,MAX_DESCRIPTION, f ) == NULL)
goto END;
}
properties->description[strlen(properties->description) - 1] = 0;

//problem
do{
while(str[0] == '\n')
if(fgets(str,MAX_DESCRIPTION, f ) == NULL)
goto END;

tmp = new Key_Value;
tmp->description[0] = 0;
int i;
while(str[0] == '#') {
sprintf(tmp->description + strlen(tmp->description), "%s", str + 2);
if(fgets(str,MAX_DESCRIPTION, f ) == NULL)
goto END;
}
tmp->description[strlen(tmp->description) - 1] = 0;

if(str[0] != '\0' && str[0] != '\n') {
for(i = 0;str[i] != '=' && i < MAX_KEY; i ++);
copy(tmp->key,str, i + 1);
copy(tmp->value, str + i + 1, MAX_VALUE);
tmp->value[strlen(tmp->value) - 1] = 0;
tmp->level = 0;
last->next = tmp;
last = tmp;
properties->len ++;
}
if(fgets(str,MAX_DESCRIPTION, f ) == NULL)
goto END;
} while(!feof(f)) ;
END :
last->next = NULL;
fclose(f);
}

/*
0 -- it self
1 -- previous
*/
Key_Value *Config::index(const char *key, int flag) {
Key_Value  *next = properties->head;
for(int i = 0;i < properties->len && next->next;i ++) {
if(strcmp(next->next->key, key) == 0) {
if(flag)
return next;
else if(flag == 0)
return next->next;
}
next = next->next;
}
return NULL;
}

void Config::write() {
if(rwable() != S_W && rwable() != S_RW)
return ;
FILE *f =  fopen(properties->path, "w");
Key_Value  *next = properties->head->next;
char tmp[MAX_DESCRIPTION];
if(properties->description[0] != 0) {
fputc('#',f);
fputc(' ',f);
for(int i = 0; i < strlen(properties->description); i ++) {
fputc(properties->description[i],f);
if(properties->description[i] == '\n' && i != strlen(properties->description) - 1) {
fputc('#',f);
fputc(' ',f);
}
}
fputc('\n',f);
fputc('\n',f);
}

for(int i = 0; i < properties->len && next; i ++) {
if(next->description[0] != 0) {
fputc('#',f);
fputc(' ',f);
for(int j = 0; j < strlen(next->description); j ++) {
fputc(next->description[j], f);
if(next->description[j] == '\n' && i != strlen(next->description) - 1) {
fputc('#',f);
fputc(' ',f);
}
}
fputc('\n',f);
}
sprintf(tmp, "%s=%s\n\n", next->key, next->value);
fwrite(tmp, 1, strlen(tmp), f);
next = next->next;
}
fclose(f);
properties->changed = 0;
}

void Config::copy(char *dest, const char *source, int m_size) {
int size = strlen(source) < m_size -1 ? strlen(source) : m_size - 1;
strncpy(dest, source, size);
dest[size] = 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: