免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123下一页
最近访问板块 发新帖
查看: 13941 | 回复: 23
打印 上一主题 下一主题

ini文件解析器 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-11-25 18:43 |只看该作者 |倒序浏览
本帖最后由 SoforthHe 于 2011-11-25 18:46 编辑

今天做了一个简单的ini文件解析器,代码如下:
  1. /**
  2. * Copyright(C) 2011 soforth <justhechuang@163.com>
  3. *
  4. * a ini file parser
  5. *                          
  6. * This program/include file is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License as published
  8. * by the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program/include file is distributed in the hope that it will be
  12. * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
  13. * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. */

  16. #include <stdlib.h>
  17. #include <unistd.h>
  18. #include <string.h>
  19. #include <stdio.h>
  20. #include <fcntl.h>
  21. #include <sys/mman.h>

  22. #include "list.h"

  23. #define MAX_BUCK_NUM        256  /* should be more than 0xff */
  24. #define MAX_NAME_SIZE       80

  25. #if !defined(__GNUC__) || (__GNUC__ == 2 && __GNUC_MINOR__ < 96)           
  26. #define __builtin_expect(x, expected_value) (x)                           
  27. #endif
  28. #define likely(x)       __builtin_expect((x),1)                           
  29. #define unlikely(x)     __builtin_expect((x),0)

  30. typedef struct _SECTION {
  31.         list_head_t list;      /* section list */
  32.         list_head_t key_list;  /* key list */
  33.         char name[MAX_NAME_SIZE];
  34. }SECTION, *PSECTION;

  35. typedef struct _KEY_VALUE {
  36.         list_head_t list;        /* key-value list */
  37.         int intval;
  38.         char key[MAX_NAME_SIZE];
  39.         char value[BUFSIZ];
  40. }KEY_VALUE, *PKEY_VALUE;

  41. static list_head_t   section_list[MAX_BUCK_NUM] = { 0 };
  42. #define INIT_SECTION_LIST() do{ int i;for( i = 0; i < MAX_BUCK_NUM; ++i ) INIT_LIST_HEAD(&section_list[i]);}while(0)

  43. static const char sep[256] = { [' ']=1, ['.']=1, ['-']=1, ['_']=1 };
  44. #define SEP(x,y) sep[*((unsigned char *)(x) + (y))]


  45. static __inline unsigned AtBuckIndex(const char *section) {
  46.         unsigned h = 0;
  47.         while(*section) {
  48.                 h = h * 11 + (*section<<4) + (*section>>4);
  49.                 section++;
  50.         }
  51.         return h&0xff;
  52. }

  53. static __inline PSECTION AtSection(const char* section) {
  54.         list_head_t *l;
  55.         PSECTION sec;
  56.         unsigned idx;
  57.         if(unlikely(NULL==section)){
  58.                 return NULL;
  59.         }
  60.         idx = AtBuckIndex(section);
  61.         list_for_each(l, &section_list[idx]) {
  62.                 sec = list_entry(l, SECTION, list);
  63.                 if(sec && !strcasecmp(section, sec->name)) {
  64.                         return sec;
  65.                 }
  66.         }
  67.         return NULL;
  68. }

  69. static __inline PKEY_VALUE AtKeyValue(const PSECTION section, const char*key) {
  70.         list_head_t *l;
  71.         PKEY_VALUE kv;
  72.         if(unlikely(NULL==section||NULL==key)){
  73.                 return NULL;
  74.         }
  75.         list_for_each(l, &section->key_list) {
  76.                 kv = list_entry(l, KEY_VALUE, list);
  77.                 if(kv && !strcasecmp(key, kv->key) ) {
  78.                         return kv;
  79.                 }
  80.         }
  81.         return NULL;
  82. }

  83. int parser_delete_key(const char* section, const char*key ) {
  84.         PSECTION sec;
  85.         PKEY_VALUE kv;

  86.         if(unlikely(NULL==section||NULL==key)){
  87.                 return -1;
  88.         }

  89.         if((sec=AtSection(section))&&(kv=AtKeyValue(sec, key))) {
  90.                 list_del(&kv->list);
  91.                 free(kv);
  92.                 return 0;
  93.         }       

  94.         return -1;
  95. }

  96. int parser_delete_section(const char* section) {
  97.         list_head_t *l;
  98.         list_head_t *tmp;
  99.         PSECTION sec;
  100.         PKEY_VALUE kv;

  101.         if(unlikely(NULL==section)){
  102.                 return -1;
  103.         }

  104.         if((sec=AtSection(section))) {
  105.                 list_for_each_entry_safe_l(kv, tmp, &sec->key_list, list) {
  106.                         list_del(&kv->list);
  107.                         free(kv);
  108.                 }
  109.                 list_del(&sec->list);
  110.                 free(sec);
  111.                 return 0;
  112.         }

  113.         return -1;
  114. }

  115. char *parser_get_string(const char* section, const char* key) {
  116.         PSECTION sec;
  117.         PKEY_VALUE kv;

  118.         if(unlikely(NULL==section||NULL==key)){
  119.                 return NULL;
  120.         }

  121.         if((sec=AtSection(section)) &&(kv=AtKeyValue(sec, key))) {
  122.                 return kv->value;
  123.         }       

  124.         return NULL;
  125. }

  126. int parser_set_string(const char* section, const char* key, const char* value) {
  127.         PSECTION sec;
  128.         PKEY_VALUE kv;
  129.         unsigned idx;

  130.         if(unlikely(NULL==section||NULL==key)){
  131.                 return -1;
  132.         }

  133.         if((sec=AtSection(section))&&(kv=AtKeyValue(sec, key))) {
  134.                 strncpy(kv->value, value, BUFSIZ);
  135.                 kv->intval = -1;
  136.                 return 0;
  137.         }       
  138.         if( sec ) {
  139.                 kv = (PKEY_VALUE)malloc(sizeof(KEY_VALUE));
  140.                 strncpy(kv->key, key, MAX_NAME_SIZE);
  141.                 strncpy(kv->value, value, BUFSIZ);
  142.                 kv->intval = -1;
  143.                 list_add(&kv->list, &sec->key_list);
  144.                 return 0;
  145.         }else {
  146.                 sec = (PSECTION)malloc(sizeof(SECTION));
  147.                 idx = AtBuckIndex(section);
  148.                 strncpy(sec->name, section, MAX_NAME_SIZE);
  149.                 INIT_LIST_HEAD(&sec->key_list);
  150.                 list_add(&sec->list, &section_list[idx]);

  151.                 kv = (PKEY_VALUE)malloc(sizeof(KEY_VALUE));
  152.                 strncpy(kv->key, key, MAX_NAME_SIZE);
  153.                 strncpy(kv->value, value, BUFSIZ);
  154.                 kv->intval = -1;
  155.                 list_add(&kv->list, &sec->key_list);
  156.                 return 0;       
  157.         }

  158.         return -1;
  159. }

  160. static int map_file(const char* filename, char** buf, int *len) {
  161.         int fd;

  162.         if(unlikely(NULL==filename)) {
  163.                 return -1;
  164.         }

  165.         fd = open(filename, O_RDONLY);
  166.         if(fd < 0) return -1;

  167.         *len = lseek(fd, 0L, SEEK_END);
  168.         lseek(fd, 0L, SEEK_SET);

  169.         *buf = mmap(0, *len+1, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
  170.         if(*buf == MAP_FAILED) {
  171.                 close(fd);
  172.                 return -1;
  173.         }
  174.         if(read(fd, *buf, *len)<0) {
  175.                 close(fd);
  176.                 return -1;
  177.         }
  178.         close(fd);

  179.         return 0;
  180. }

  181. static int parser_init(const char* filename){
  182.         static int inited = 0;
  183.         char *buf;
  184.         int len;
  185.         char *p, *pn, *k, *v;
  186.         char *section = "";

  187.         if( map_file(filename, &buf, &len) < 0 ) {
  188.                 return -1;
  189.         }

  190.         if( !inited  ) {
  191.                 INIT_SECTION_LIST();
  192.                 inited = 1;
  193.         }

  194.         buf[len] = '\0';
  195.         p = buf;

  196.         while(p < buf+len) {
  197.                 pn = strchr(p, '\n');
  198.                 if(pn) {
  199.                         *pn++ = '\0';
  200.                 }
  201.                 p += strspn(p, " \t\r"); /* skip leading blanks */
  202.                 if(*p == '[') {
  203.                         char *q = strchr(++p, ']');
  204.                         if(q) {
  205.                                 while(SEP(q, -1)){ q--; }
  206.                                 *q = '\0';
  207.                                 while(SEP(p, 0)) { p++; }
  208.                                 if(p[0] == '\0') {
  209.                                         section = "";
  210.                                 } else {
  211.                                         section = p;
  212.                                 }
  213.                         }
  214.                 } else if(*p && *p != '#' && *p != ';'){
  215.                         k = p;
  216.                         p += strcspn(p, " \t\r=");
  217.                         v = p;                   /* v is end of key */
  218.                         p += strspn(p, " \t\r"); /* skip blanks between key and = */
  219.                         if(*p == '=') {
  220.                                 while(*++p == '=') { ; }  
  221.                         }
  222.                         *v = '\0';
  223.                         v = p + strspn(p, " \t\r");
  224.                         p = pn ? pn - 2 : p+strlen(p)-1;
  225.                         while(*p == ' '|| *p == '\t' || *p == '\r') {*p-- = '\0';}        /* strip trailling blanks */

  226.                         if(k && v) {
  227.                                 parser_set_string(section, k, v);
  228.                         }
  229.                 }
  230.                 p = pn;
  231.         }

  232.         munmap(buf, len+1);

  233.         return 0;
  234. }

  235. int parser_get_intval(const char *section, const char *key, int def){
  236.         PKEY_VALUE kv;

  237.         kv = AtKeyValue(AtSection(section), key);

  238.         if(unlikely(NULL==kv)) {
  239.                 return def;
  240.         }

  241.         if(kv->intval != -1) {
  242.                 return kv->intval;
  243.         }

  244.         if(isdigit(kv->value[0])||(kv->value[0]=='-'&&isdigit(kv->value[1]))) {
  245.                 kv->intval = atol(kv->value);
  246.         }else if(!strcasecmp(kv->value, "On")){
  247.                 kv->intval = 1;
  248.         }else if(!strcasecmp(kv->value, "Off")){
  249.                 kv->intval = 0;
  250.         }else if(!strcasecmp(kv->value, "Yes")){
  251.                 kv->intval = 1;
  252.         }else if(!strcasecmp(kv->value, "No")){
  253.                 kv->intval = 0;
  254.         }else if(!strcasecmp(kv->value, "True")){
  255.                 kv->intval = 1;
  256.         }else if(!strcasecmp(kv->value, "False")){
  257.                 kv->intval = 0;
  258.         }else if(!strcasecmp(kv->value, "enable")){
  259.                 kv->intval = 1;
  260.         }else if(!strcasecmp(kv->value, "disable")){
  261.                 kv->intval = 0;
  262.         }else if(!strcasecmp(kv->value, "enabled")){
  263.                 kv->intval = 1;
  264.         }else if(!strcasecmp(kv->value, "disabled")){
  265.                 kv->intval = 0;
  266.         }else {
  267.                 return def;
  268.         }

  269.         return kv->intval;
  270. }

  271. unsigned long parser_get_size(const char *section, const char *key, unsigned long def) {
  272.         PKEY_VALUE kv;
  273.         char *pp;
  274.         unsigned long v;

  275.         kv = AtKeyValue(AtSection(section), key);

  276.         if(unlikely(NULL==kv)) {
  277.                 return def;
  278.         }

  279.         if(!isdigit(kv->value[0])) {
  280.                 return def;
  281.         }

  282.         v = strtoul(kv->value, &pp, 0);
  283.         if(pp[0] == 'K' || pp[0] == 'k') {
  284.                 v *= 1024;
  285.         }else if(pp[0] == 'M' || pp[0] == 'm') {
  286.                 v *= 1024*1024;
  287.         }else if(pp[0] == 'G' || pp[0] == 'g') {
  288.                 v *= 1024*1024*1024;
  289.         }

  290.         return v;
  291. }

  292. int parser_dump(char* filename) {
  293.         list_head_t *ls,*lk;
  294.         PSECTION sec;
  295.         PKEY_VALUE kv;
  296.         int i;

  297.         FILE *fp;

  298.         if(!(fp=fopen(filename, "w"))){
  299.                 fprintf(stderr, "parser_dump: open %s error [%d]\n", filename, __LINE__);
  300.                 return -1;
  301.         }

  302.         for( i = 0; i < MAX_BUCK_NUM; ++i) {
  303.                 list_for_each(ls, &section_list[i]) {
  304.                         sec = list_entry(ls, SECTION, list );
  305.                         if(!sec) continue;
  306.                         fprintf(fp, "[ %s ]\n", sec->name);
  307.                         list_for_each(lk, &sec->key_list){
  308.                                 if(!lk) continue;
  309.                                 kv = list_entry(lk, KEY_VALUE, list);
  310.                                 fprintf(fp, "%s=%s\n", kv->key, kv->value);
  311.                         }
  312.                 }
  313.         }

  314.         fclose(fp);

  315.         return 0;
  316. }

  317. int main(int argc, char** argv) {
  318.         if( argc < 2 ) {
  319.                 printf("Usage: %s <config.ini>\n", argv[0]);
  320.                 return -1;
  321.         }
  322.         parser_init(argv[1]);

  323.         int ch;
  324.         char secbuf[255];
  325.         char keybuf[255];
  326.         char valbuf[255];
  327.         char filebuf[255];
  328.         while((ch=getchar())!='q') {
  329.                 switch(ch){
  330.                         case 'g':
  331.                                 printf("input section name: ");
  332.                                 scanf("%s", secbuf);
  333.                                 printf("input key name: ");
  334.                                 scanf("%s", keybuf);
  335.                                 printf("[VALUE: %s]\n", parser_get_string(secbuf, keybuf));                               
  336.                                 printf("[VALUE: %d]\n", parser_get_intval(secbuf, keybuf, -1));       
  337.                                 printf("[VALUE: %lu]\n", parser_get_size(secbuf, keybuf, -1));       
  338.                                 break;
  339.                         case 's':
  340.                                 printf("input section name: ");
  341.                                 scanf("%s", secbuf);
  342.                                 printf("input key name: ");
  343.                                 scanf("%s", keybuf);
  344.                                 printf("input value: ");
  345.                                 scanf("%s", valbuf);
  346.                                 parser_set_string(secbuf, keybuf, valbuf);
  347.                                 break;
  348.                         case 'D':
  349.                                 printf("input section name: ");
  350.                                 scanf("%s", secbuf);
  351.                                 printf("input key name: ");
  352.                                 scanf("%s", keybuf);
  353.                                 parser_delete_key(secbuf,keybuf);
  354.                                 break;
  355.                         case 'r':
  356.                                 printf("input section name: ");
  357.                                 scanf("%s", secbuf);
  358.                                 parser_delete_section(secbuf);
  359.                                 break;
  360.                         case 'd':
  361.                                 printf("input filename to dump: ");
  362.                                 scanf("%s", filebuf);
  363.                                 parser_dump(filebuf);
  364.                                 break;                               
  365.                 }
  366.         }

  367.         return 0;
  368. }
复制代码

论坛徽章:
0
2 [报告]
发表于 2011-11-25 20:09 |只看该作者
最近正好需要这个 拜读下楼主大作

论坛徽章:
26
处女座
日期:2016-04-18 14:00:4515-16赛季CBA联赛之深圳
日期:2020-06-02 10:10:5015-16赛季CBA联赛之广夏
日期:2019-07-23 16:59:452016科比退役纪念章
日期:2019-06-26 16:59:1315-16赛季CBA联赛之天津
日期:2019-05-28 14:25:1915-16赛季CBA联赛之青岛
日期:2019-05-16 10:14:082016科比退役纪念章
日期:2019-01-11 14:44:062016科比退役纪念章
日期:2018-07-18 16:17:4015-16赛季CBA联赛之上海
日期:2017-08-22 18:18:5515-16赛季CBA联赛之江苏
日期:2017-08-04 17:00:4715-16赛季CBA联赛之佛山
日期:2017-02-20 18:21:1315-16赛季CBA联赛之天津
日期:2016-12-12 10:44:23
3 [报告]
发表于 2011-11-25 23:24 |只看该作者
楼主能写个CSV 文件读取的类吗?

论坛徽章:
0
4 [报告]
发表于 2011-11-26 08:22 |只看该作者
楼主能写个CSV 文件读取的类吗?
evaspring 发表于 2011-11-25 23:24



    最近在完成一个项目'贴出来的是涉及到的部分'所以抱歉啦11

论坛徽章:
0
5 [报告]
发表于 2011-11-26 08:24 |只看该作者
最近正好需要这个 拜读下楼主大作
gtv 发表于 2011-11-25 20:09

论坛徽章:
0
6 [报告]
发表于 2011-11-26 08:25 |只看该作者
本帖最后由 三月廿七 于 2011-11-26 08:26 编辑
SoforthHe 发表于 2011-11-26 08:24


楼主能不能写个 xml 解析器, ini 没什么用途

论坛徽章:
0
7 [报告]
发表于 2011-11-26 08:30 |只看该作者
楼主能不能写个 xml 解析器, ini 没什么用途
三月廿七 发表于 2011-11-26 08:25



    网上开源的一堆啊'对我来说实用就够了

论坛徽章:
2
CU十二周年纪念徽章
日期:2013-10-24 15:41:34处女座
日期:2013-12-27 22:22:41
8 [报告]
发表于 2011-11-26 12:58 |只看该作者
这东西要我做就用Python了。

论坛徽章:
2
技术图书徽章
日期:2013-09-04 15:21:51酉鸡
日期:2013-11-01 21:20:20
9 [报告]
发表于 2011-11-26 14:58 |只看该作者
解析key/value,用sscanf很好用.

论坛徽章:
2
技术图书徽章
日期:2013-09-04 15:21:51酉鸡
日期:2013-11-01 21:20:20
10 [报告]
发表于 2011-11-26 14:59 |只看该作者
楼主能不能写个 xml 解析器, ini 没什么用途
三月廿七 发表于 2011-11-26 08:25



   libxml不能满足要求吗?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP