C语言解析Ini格式文件

皇甫德庸
2023-12-01
 

引用别人的博文: http://www.open-open.com/lib/view/open1402278076447.html

可以解析 INI 格式的字符串、解析文件、保存到文件。

    下面是头文件:

  1 #ifndef INI_PARSER_H
  2 #define INI_PARSER_H
  3 #ifdef __cplusplus
  4 extern "C" {
  5 #endif
  6 struct tag_value_list;
  7 
  8 struct ini_parser {
  9     struct tag_value_list * keyvalues;
 10     int (*parse_file)(struct ini_parser *, const char * file);
 11     int (*parse_string)(struct ini_parser *, const char *text);
 12     char * (*value)(struct ini_parser *, const char * key);
 13     void (*set_value)(struct ini_parser *, const char * key, const char * value);
 14     void (*remove)(struct ini_parser *, const char *key);
 15     int (*save_to_file)(struct ini_parser *, const char * file);
 16 };
 17 
 18 struct ini_parser * new_ini_parser();
 19 void delete_ini_parser(struct ini_parser *);
 20 
 21 #ifdef __cplusplus
 22 }
 23 #endif
 24 #endif // INI_PARSER_H
 25 下面是源文件:
 26 #include "ini_parser.h"
 27 #include <stdio.h>
 28 #include <string.h>
 29 #include "tag_value.h"
 30 
 31 static struct tag_value_pair * parse_line(char *line, int len)
 32 {
 33     struct tag_value_pair * pair = 0;
 34     int count = 0;
 35     char * p = line;
 36     char * end = 0;
 37     char * start = line;
 38     if(!p) return 0;
 39     while(*p == ' ') p++;
 40 
 41 
 42     /*blank line*/
 43     if(p - line == len ||
 44             *p == '\r' ||
 45             *p == '\n' ||
 46             *p == '\0') return 0;
 47 
 48     /*do not support group*/
 49     if(*p == '[') return 0;
 50     /*comments*/
 51     if(*p == '#') return 0;
 52 
 53     /* extract key */
 54     start = p;
 55     end = line + len;
 56     while(*p != '=' && p!= end) p++;
 57     if(p == end)
 58     {
 59         /* none '=' , invalid line */
 60         return 0;
 61     }
 62     end = p - 1;
 63     while(*end == ' ') end--; /* skip blank at the end */
 64     count = end - start + 1;
 65 
 66     pair = new_tag_value_pair();
 67     pair->szTag = malloc(count + 1);
 68     strncpy(pair->szTag, start, count);
 69     pair->szTag[count] = 0;
 70 
 71     /* extract value */
 72     p++;
 73     end = line + len; /* next pos of the last char */
 74     while( *p == ' ' && p != end) p++;
 75     if(p == end)
 76     {
 77         delete_tag_value_pair(pair);
 78         return 0;
 79     }
 80     start = p;
 81     end--; /* to the last char */
 82     if(*end == '\n') { *end = 0; end--; }
 83     if(*end == '\r') { *end = 0; end--; }
 84     count = end - start + 1;
 85     if(count > 0)
 86     {
 87         pair->szValue = malloc(count + 1);
 88         strncpy(pair->szValue, start, count);
 89         pair->szValue[count] = 0;
 90     }
 91 
 92     /* release empty key-value pair */
 93     if(!pair->szValue)
 94     {
 95         delete_tag_value_pair(pair);
 96         return 0;
 97     }
 98 
 99     return pair;
100 }
101 
102 static int _parse_file(struct ini_parser * ini, const char *file){
103     FILE * fp = fopen(file, "r");
104     if(fp)
105     {
106         struct tag_value_pair * pair = 0;
107         char buf[1024] = {0};
108         while(fgets(buf, 1024, fp))
109         {
110             pair = parse_line(buf, strlen(buf));
111             if(pair)
112             {
113                 ini->keyvalues->add(ini->keyvalues, pair);
114             }
115         }
116         fclose(fp);
117         return ini->keyvalues->size;
118     }
119     return -1;
120 }
121 
122 static int _parse_text(struct ini_parser * ini, const char * text){
123     char *p = text;
124     char * start = 0;
125     struct tag_value_pair * pair = 0;
126     if(!text) return -1;
127 
128     while(1)
129     {
130         start = p;
131         while(*p != '\n' && *p != '\0' )p++;
132         if(*p == '\0') break;
133 
134         pair = parse_line(start, p - start);
135         if(pair) ini->keyvalues->add(ini->keyvalues, pair);
136 
137         p++;
138     }
139 
140     return ini->keyvalues->size;
141 }
142 
143 static char * _value(struct ini_parser * ini, const char * key){
144     struct tag_value_pair * pair = ini->keyvalues->find_by_tag(ini->keyvalues, key);
145     if(pair) return pair->szValue;
146     return 0;
147 }
148 
149 static void _set_value(struct ini_parser * ini, const char * key, const char *value){
150     struct tag_value_pair * pair = ini->keyvalues->find_by_tag(ini->keyvalues, key);
151     if(pair)
152     {
153         if(pair->szValue) free(pair->szValue);
154         pair->szValue = strdup(value);
155     }
156     else
157     {
158         ini->keyvalues->add(ini->keyvalues, make_tag_value_pair(key, value));
159     }
160 }
161 
162 static void _remove(struct ini_parser * ini, const char * key){
163     struct tag_value_pair * pair = ini->keyvalues->find_by_tag(ini->keyvalues, key);
164     if(pair)ini->keyvalues->remove(ini->keyvalues, pair);
165 }
166 
167 static void write_keyvalue(struct tag_value_pair * pair, FILE *fp)
168 {
169     fputs(pair->szTag, fp);
170     fputc('=', fp);
171     fputs(pair->szValue, fp);
172     fputc('\n', fp);
173 }
174 
175 static int _save_to_file(struct ini_parser * ini, const char * file){
176     if(ini->keyvalues->size > 0)
177     {
178         FILE * fp = fopen(file, "w");
179         if(fp)
180         {
181             struct tag_value_pair * pair = ini->keyvalues->head;
182             while(pair != ini->keyvalues->tail)
183             {
184                 write_keyvalue(pair, fp);
185                 pair = pair->next;
186             }
187 
188             if(pair)write_keyvalue(pair, fp);
189 
190             fclose(fp);
191             return 0;
192         }
193     }
194     return -1;
195 }
196 
197 struct ini_parser * new_ini_parser(){
198     struct ini_parser * ini = (struct ini_parser*)malloc(sizeof(struct ini_parser));
199     ini->keyvalues = new_tag_value_list();
200     ini->parse_file = _parse_file;
201     ini->parse_string = _parse_text;
202     ini->value = _value;
203     ini->set_value = _set_value;
204     ini->remove = _remove;
205     ini->save_to_file = _save_to_file;
206     return ini;
207 }
208 
209 void delete_ini_parser(struct ini_parser *ini){
210     if(ini)
211     {
212         delete_tag_value_list(ini->keyvalues);
213         free(ini);
214     }
215 }
216     测试代码:
217 #include "util/ini_parser.h"
218 #include "ini_test.h"
219 #include <stdio.h>
220 #include <assert.h>
221 
222 static char * g_szIniString = "#abc\nfirst=2\nsecond\nname=charli  zhang \n";
223 
224 static void ini_parser_test_string()
225 {
226     struct ini_parser * ini = new_ini_parser();
227     int size = ini->parse_string(ini, g_szIniString);
228 
229     assert( size > 0);
230     assert( ini->value(ini, "second") == 0 );
231     assert( ini->value(ini, "abc") == 0);
232     assert( ini->value(ini, "name") != NULL );
233     assert( ini->value(ini, "first") != NULL);
234 
235     printf("ini string: %s\n", g_szIniString);
236     printf("key-value pairs count = %d\n", size);
237     printf("key \'name\'', value = %s\n", ini->value(ini, "name"));
238     printf("key \'first\'', value = %s\n", ini->value(ini, "first"));
239 
240     ini->set_value(ini, "baidu", "hahaha");
241     ini->save_to_file(ini, "write.conf");
242 
243     ini->remove(ini, "first");
244     ini->save_to_file(ini, "write2.conf");
245 
246     delete_ini_parser(ini);
247 }
248 
249 static void ini_parser_test_file()
250 {
251     struct ini_parser * ini = new_ini_parser();
252     int size = ini->parse_file(ini, "test.conf");
253 
254     assert( size > 0);
255     assert( ini->value(ini, "second") == 0 );
256     assert( ini->value(ini, "abc") == 0);
257     assert( ini->value(ini, "name") != NULL );
258     assert( ini->value(ini, "first") != NULL);
259 
260     printf("ini string: %s\n", g_szIniString);
261     printf("key-value pairs count = %d\n", size);
262     printf("key \'name\'', value = %s\n", ini->value(ini, "name"));
263     printf("key \'first\'', value = %s\n", ini->value(ini, "first"));
264     printf("key \'baidu\'', value = %s\n", ini->value(ini, "baidu"));
265 
266     delete_ini_parser(ini);
267 }
268 
269 void ini_parser_test()
270 {
271     ini_parser_test_string();
272     ini_parser_test_file();
273 }

 

 类似资料: