- 论坛徽章:
- 0
|
本帖最后由 SoforthHe 于 2011-11-25 18:46 编辑
今天做了一个简单的ini文件解析器,代码如下:- /**
- * Copyright(C) 2011 soforth <justhechuang@163.com>
- *
- * a ini file parser
- *
- * This program/include file is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program/include file is distributed in the hope that it will be
- * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
- #include <stdlib.h>
- #include <unistd.h>
- #include <string.h>
- #include <stdio.h>
- #include <fcntl.h>
- #include <sys/mman.h>
- #include "list.h"
- #define MAX_BUCK_NUM 256 /* should be more than 0xff */
- #define MAX_NAME_SIZE 80
- #if !defined(__GNUC__) || (__GNUC__ == 2 && __GNUC_MINOR__ < 96)
- #define __builtin_expect(x, expected_value) (x)
- #endif
- #define likely(x) __builtin_expect((x),1)
- #define unlikely(x) __builtin_expect((x),0)
- typedef struct _SECTION {
- list_head_t list; /* section list */
- list_head_t key_list; /* key list */
- char name[MAX_NAME_SIZE];
- }SECTION, *PSECTION;
- typedef struct _KEY_VALUE {
- list_head_t list; /* key-value list */
- int intval;
- char key[MAX_NAME_SIZE];
- char value[BUFSIZ];
- }KEY_VALUE, *PKEY_VALUE;
- static list_head_t section_list[MAX_BUCK_NUM] = { 0 };
- #define INIT_SECTION_LIST() do{ int i;for( i = 0; i < MAX_BUCK_NUM; ++i ) INIT_LIST_HEAD(§ion_list[i]);}while(0)
- static const char sep[256] = { [' ']=1, ['.']=1, ['-']=1, ['_']=1 };
- #define SEP(x,y) sep[*((unsigned char *)(x) + (y))]
- static __inline unsigned AtBuckIndex(const char *section) {
- unsigned h = 0;
- while(*section) {
- h = h * 11 + (*section<<4) + (*section>>4);
- section++;
- }
- return h&0xff;
- }
- static __inline PSECTION AtSection(const char* section) {
- list_head_t *l;
- PSECTION sec;
- unsigned idx;
- if(unlikely(NULL==section)){
- return NULL;
- }
- idx = AtBuckIndex(section);
- list_for_each(l, §ion_list[idx]) {
- sec = list_entry(l, SECTION, list);
- if(sec && !strcasecmp(section, sec->name)) {
- return sec;
- }
- }
- return NULL;
- }
- static __inline PKEY_VALUE AtKeyValue(const PSECTION section, const char*key) {
- list_head_t *l;
- PKEY_VALUE kv;
- if(unlikely(NULL==section||NULL==key)){
- return NULL;
- }
- list_for_each(l, §ion->key_list) {
- kv = list_entry(l, KEY_VALUE, list);
- if(kv && !strcasecmp(key, kv->key) ) {
- return kv;
- }
- }
- return NULL;
- }
- int parser_delete_key(const char* section, const char*key ) {
- PSECTION sec;
- PKEY_VALUE kv;
- if(unlikely(NULL==section||NULL==key)){
- return -1;
- }
- if((sec=AtSection(section))&&(kv=AtKeyValue(sec, key))) {
- list_del(&kv->list);
- free(kv);
- return 0;
- }
- return -1;
- }
- int parser_delete_section(const char* section) {
- list_head_t *l;
- list_head_t *tmp;
- PSECTION sec;
- PKEY_VALUE kv;
- if(unlikely(NULL==section)){
- return -1;
- }
- if((sec=AtSection(section))) {
- list_for_each_entry_safe_l(kv, tmp, &sec->key_list, list) {
- list_del(&kv->list);
- free(kv);
- }
- list_del(&sec->list);
- free(sec);
- return 0;
- }
- return -1;
- }
- char *parser_get_string(const char* section, const char* key) {
- PSECTION sec;
- PKEY_VALUE kv;
- if(unlikely(NULL==section||NULL==key)){
- return NULL;
- }
- if((sec=AtSection(section)) &&(kv=AtKeyValue(sec, key))) {
- return kv->value;
- }
- return NULL;
- }
- int parser_set_string(const char* section, const char* key, const char* value) {
- PSECTION sec;
- PKEY_VALUE kv;
- unsigned idx;
- if(unlikely(NULL==section||NULL==key)){
- return -1;
- }
- if((sec=AtSection(section))&&(kv=AtKeyValue(sec, key))) {
- strncpy(kv->value, value, BUFSIZ);
- kv->intval = -1;
- return 0;
- }
- if( sec ) {
- kv = (PKEY_VALUE)malloc(sizeof(KEY_VALUE));
- strncpy(kv->key, key, MAX_NAME_SIZE);
- strncpy(kv->value, value, BUFSIZ);
- kv->intval = -1;
- list_add(&kv->list, &sec->key_list);
- return 0;
- }else {
- sec = (PSECTION)malloc(sizeof(SECTION));
- idx = AtBuckIndex(section);
- strncpy(sec->name, section, MAX_NAME_SIZE);
- INIT_LIST_HEAD(&sec->key_list);
- list_add(&sec->list, §ion_list[idx]);
- kv = (PKEY_VALUE)malloc(sizeof(KEY_VALUE));
- strncpy(kv->key, key, MAX_NAME_SIZE);
- strncpy(kv->value, value, BUFSIZ);
- kv->intval = -1;
- list_add(&kv->list, &sec->key_list);
- return 0;
- }
- return -1;
- }
- static int map_file(const char* filename, char** buf, int *len) {
- int fd;
- if(unlikely(NULL==filename)) {
- return -1;
- }
- fd = open(filename, O_RDONLY);
- if(fd < 0) return -1;
- *len = lseek(fd, 0L, SEEK_END);
- lseek(fd, 0L, SEEK_SET);
- *buf = mmap(0, *len+1, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- if(*buf == MAP_FAILED) {
- close(fd);
- return -1;
- }
- if(read(fd, *buf, *len)<0) {
- close(fd);
- return -1;
- }
- close(fd);
- return 0;
- }
- static int parser_init(const char* filename){
- static int inited = 0;
- char *buf;
- int len;
- char *p, *pn, *k, *v;
- char *section = "";
- if( map_file(filename, &buf, &len) < 0 ) {
- return -1;
- }
- if( !inited ) {
- INIT_SECTION_LIST();
- inited = 1;
- }
- buf[len] = '\0';
- p = buf;
- while(p < buf+len) {
- pn = strchr(p, '\n');
- if(pn) {
- *pn++ = '\0';
- }
- p += strspn(p, " \t\r"); /* skip leading blanks */
- if(*p == '[') {
- char *q = strchr(++p, ']');
- if(q) {
- while(SEP(q, -1)){ q--; }
- *q = '\0';
- while(SEP(p, 0)) { p++; }
- if(p[0] == '\0') {
- section = "";
- } else {
- section = p;
- }
- }
- } else if(*p && *p != '#' && *p != ';'){
- k = p;
- p += strcspn(p, " \t\r=");
- v = p; /* v is end of key */
- p += strspn(p, " \t\r"); /* skip blanks between key and = */
- if(*p == '=') {
- while(*++p == '=') { ; }
- }
- *v = '\0';
- v = p + strspn(p, " \t\r");
- p = pn ? pn - 2 : p+strlen(p)-1;
- while(*p == ' '|| *p == '\t' || *p == '\r') {*p-- = '\0';} /* strip trailling blanks */
- if(k && v) {
- parser_set_string(section, k, v);
- }
- }
- p = pn;
- }
- munmap(buf, len+1);
- return 0;
- }
- int parser_get_intval(const char *section, const char *key, int def){
- PKEY_VALUE kv;
- kv = AtKeyValue(AtSection(section), key);
- if(unlikely(NULL==kv)) {
- return def;
- }
- if(kv->intval != -1) {
- return kv->intval;
- }
- if(isdigit(kv->value[0])||(kv->value[0]=='-'&&isdigit(kv->value[1]))) {
- kv->intval = atol(kv->value);
- }else if(!strcasecmp(kv->value, "On")){
- kv->intval = 1;
- }else if(!strcasecmp(kv->value, "Off")){
- kv->intval = 0;
- }else if(!strcasecmp(kv->value, "Yes")){
- kv->intval = 1;
- }else if(!strcasecmp(kv->value, "No")){
- kv->intval = 0;
- }else if(!strcasecmp(kv->value, "True")){
- kv->intval = 1;
- }else if(!strcasecmp(kv->value, "False")){
- kv->intval = 0;
- }else if(!strcasecmp(kv->value, "enable")){
- kv->intval = 1;
- }else if(!strcasecmp(kv->value, "disable")){
- kv->intval = 0;
- }else if(!strcasecmp(kv->value, "enabled")){
- kv->intval = 1;
- }else if(!strcasecmp(kv->value, "disabled")){
- kv->intval = 0;
- }else {
- return def;
- }
- return kv->intval;
- }
- unsigned long parser_get_size(const char *section, const char *key, unsigned long def) {
- PKEY_VALUE kv;
- char *pp;
- unsigned long v;
- kv = AtKeyValue(AtSection(section), key);
- if(unlikely(NULL==kv)) {
- return def;
- }
- if(!isdigit(kv->value[0])) {
- return def;
- }
- v = strtoul(kv->value, &pp, 0);
- if(pp[0] == 'K' || pp[0] == 'k') {
- v *= 1024;
- }else if(pp[0] == 'M' || pp[0] == 'm') {
- v *= 1024*1024;
- }else if(pp[0] == 'G' || pp[0] == 'g') {
- v *= 1024*1024*1024;
- }
- return v;
- }
- int parser_dump(char* filename) {
- list_head_t *ls,*lk;
- PSECTION sec;
- PKEY_VALUE kv;
- int i;
- FILE *fp;
- if(!(fp=fopen(filename, "w"))){
- fprintf(stderr, "parser_dump: open %s error [%d]\n", filename, __LINE__);
- return -1;
- }
- for( i = 0; i < MAX_BUCK_NUM; ++i) {
- list_for_each(ls, §ion_list[i]) {
- sec = list_entry(ls, SECTION, list );
- if(!sec) continue;
- fprintf(fp, "[ %s ]\n", sec->name);
- list_for_each(lk, &sec->key_list){
- if(!lk) continue;
- kv = list_entry(lk, KEY_VALUE, list);
- fprintf(fp, "%s=%s\n", kv->key, kv->value);
- }
- }
- }
- fclose(fp);
- return 0;
- }
- int main(int argc, char** argv) {
- if( argc < 2 ) {
- printf("Usage: %s <config.ini>\n", argv[0]);
- return -1;
- }
- parser_init(argv[1]);
- int ch;
- char secbuf[255];
- char keybuf[255];
- char valbuf[255];
- char filebuf[255];
- while((ch=getchar())!='q') {
- switch(ch){
- case 'g':
- printf("input section name: ");
- scanf("%s", secbuf);
- printf("input key name: ");
- scanf("%s", keybuf);
- printf("[VALUE: %s]\n", parser_get_string(secbuf, keybuf));
- printf("[VALUE: %d]\n", parser_get_intval(secbuf, keybuf, -1));
- printf("[VALUE: %lu]\n", parser_get_size(secbuf, keybuf, -1));
- break;
- case 's':
- printf("input section name: ");
- scanf("%s", secbuf);
- printf("input key name: ");
- scanf("%s", keybuf);
- printf("input value: ");
- scanf("%s", valbuf);
- parser_set_string(secbuf, keybuf, valbuf);
- break;
- case 'D':
- printf("input section name: ");
- scanf("%s", secbuf);
- printf("input key name: ");
- scanf("%s", keybuf);
- parser_delete_key(secbuf,keybuf);
- break;
- case 'r':
- printf("input section name: ");
- scanf("%s", secbuf);
- parser_delete_section(secbuf);
- break;
- case 'd':
- printf("input filename to dump: ");
- scanf("%s", filebuf);
- parser_dump(filebuf);
- break;
- }
- }
- return 0;
- }
复制代码 |
|