C语言ini格式配置文件的读写

依赖的类

 1 /*1 utils.h
 2  *# A variety of utility functions.
 3  *# 
 4  *# Some of the functions are duplicates of well known C functions that are not 
 5  *# standard.
 6  *2 License
 7  *[
 8  *# Author: Werner Stoop
 9  *# This software is provided under the terms of the unlicense.
10  *# See http://unlicense.org/ for more details.
11  *]
12  *2 API
13  */
14 #include "stdafx.h"
15 /*@ MY_MIN(a,b)
16  *# Macro that returns the smallest of its parameters.\n
17  *# As with all macros, {{a}} and {{b}} should not have side effects.
18  */
19 #define MY_MIN(a,b) (((a)<(b))?(a):(b))
20  
21 /*@ MY_MAX(a,b)
22  *# Macro that returns the largest of its parameters.\n
23  *# As with all macros, {{a}} and {{b}} should not have side effects.
24  */
25 #define MY_MAX(a,b) (((a)>(b))?(a):(b))
26 
27 /*@ int my_stricmp(const char *p, const char *q)
28  *# Compares two strings {{p}} and {{q}} case insensitively.
29  *#
30  *# It returns 0 if the strings are the same, a positive number if {{p}} comes after {{q}},
31  *# and negative if {{p}} comes before {{q}}.
32  */
33 int my_stricmp(const char *p, const char *q);
34 
35 /*@ char *my_strdup(const char *s)
36  *# Creates a duplicate of a string {{s}} in a dynamic memory buffer.\n
37  *# The returned buffer needs to be {{free()}}d after use. It may return
38  *# {{NULL}} if the memory allocation fails.
39  */
40 char *my_strdup(const char *s);
41 
42 /*@ char *my_strlower (char *p)
43  *# Converts a string {{p}} to lowercase in place.
44  *# It returns {{p}}.
45  */
46 char *my_strlower (char *p);
47 
48 /*@ char *my_strupper (char *p)
49  *# Converts a string {{p}} to uppercase in place.
50  *# It returns {{p}}.
51  */
52 char *my_strupper (char *p);
53 
54 /*@ char *my_strtok_r(char *str, const char *delim, char **saveptr)
55  *# Works the same as {{strtok_r(3)}} for platforms which lack it.
56  */
57 char *my_strtok_r(char *str, const char *delim, char **saveptr);
58 
59 /*@ char *my_readfile (const char *fn)
60  *# Reads an entire file identified by {{fn}} into a dynamically allocated memory buffer.\n
61  *# The returned buffer needs to be {{free()}}d afterwards.\n
62  *# It returns {{NULL}} if the file could not be read.
63  */
64 char *my_readfile (const char *fn);
utils.h

 

 1 /*
 2  * A variety of utility functions.
 3  *
 4  * See utils.h for more info
 5  *
 6  * This is free and unencumbered software released into the public domain.
 7  * http://unlicense.org/
 8  */
 9 #include "stdafx.h"
10 #include <stdlib.h>
11 #include <string.h>
12 #include <stdio.h>
13 #include <ctype.h>
14 
15 /* Case insensitive strcmp()
16  */ 
17 int my_stricmp(const char *p, const char *q) { 
18     for(;*p && tolower(*p) == tolower(*q); p++, q++);
19     return tolower(*p) - tolower(*q);
20 } 
21 
22 /* strdup() is not ANSI C */
23 char *my_strdup(const char *s) {
24     char *a;
25     size_t len = strlen(s);
26     a = (char*)malloc(len + 1);
27     if(!a) return NULL;
28     memcpy(a, s, len + 1);    
29     return a;
30 }
31 
32 /* converts a string to lowercase */
33 char *my_strlower (char *p) {
34   char *s;
35   for (s = p; s[0]; s++)
36     s[0] = tolower (s[0]);
37 
38   return p;
39 }
40 
41 /* converts a string to lowercase */
42 char *my_strupper (char *p)
43 {
44   char *s;
45   for (s = p; s[0]; s++)
46     s[0] = toupper (s[0]);
47 
48   return p;
49 }
50 
51 char *my_strtok_r(char *str, const char *delim, char **saveptr) {
52     if(!str)
53         str = *saveptr;
54     if(!str[0]) {
55         *saveptr = str;
56         return NULL;    
57     }
58     char *s = strpbrk(str, delim);
59     if(s) {
60         s[0] = '\0';
61         *saveptr = s + 1;
62     } else 
63         for(*saveptr = str; (*saveptr)[0]; (*saveptr)++);
64     return str;
65 }
66 
67 /* Reads an entire file into a dynamically allocated memory buffer.
68  * The returned buffer needs to be free()d afterwards
69  */
70 char *my_readfile(const char *fname) {
71     FILE *f;
72     long len,r;
73     char *str;
74     
75     if(!(f = fopen(fname, "rb")))    
76         return NULL;
77     
78     fseek(f, 0, SEEK_END);
79     len = ftell(f);
80     rewind(f);
81     
82     if(!(str = (char*)malloc(len+2)))
83         return NULL;    
84     r = fread(str, 1, len, f);
85     
86     if(r != len) {
87         free(str);
88         return NULL;
89     }
90     
91     fclose(f);    
92     str[len] = '\0';
93     return str;
94 }
utils.cpp

ini格式配置文件的读写

  1 /*1 ini.h
  2  *#    Header file for the {*INI*} parser.\n
  3  *# 
  4  *#    This is a simple parser for {*.INI*} files. 
  5  *#    It is based around the syntax described in the Wikipedia entry at
  6  *#    {_http://en.wikipedia.org/wiki/INI_file_}\n 
  7  *#
  8  *# The API has these features:
  9  *{
 10  ** Use {{~~ini_read()}} to read an INI file from the disc into an {{~~ini_file}} 
 11  *#   structure or create an empty {{~~ini_file}} structure.
 12  ** Use {{~~ini_get()}} to retrieve values from the {{~~ini_file}} structure.
 13  ** Use {{~~ini_put()}} and {{~~ini_putf()}} to set values in the {{~~ini_file}} structure.
 14  ** Use {{~~ini_write()}} to write the contents of the {{~~ini_file}} structure back to disc.
 15  ** Use {{~~ini_free()}} to deallocate the {{~~ini_file}} structure. 
 16  ** {{~~ini_errstr()}} is used for reporting errors.
 17  *}
 18  *2 License
 19  *[
 20  *# Author: Werner Stoop
 21  *# This software is provided under the terms of the unlicense.
 22  *# See http://unlicense.org/ for more details.
 23  *]
 24  *2 API
 25  */
 26 #ifndef INI_H
 27 #define INI_H
 28 
 29 #if defined(__cplusplus)
 30 extern "C" {
 31 #endif
 32 
 33 /*
 34  *    Encapsulates a parameter-value pair in an INI section.
 35  *    Parameters are stored in a binary search tree, which attempts (but does not
 36  *    guarantee) O(log(n)) behaviour.
 37  */
 38 typedef struct INI_PAIR
 39 {
 40     char *param;        /* The parameter */
 41     char *value;        /* Its value */
 42     
 43     /* Nodes in the tree */
 44     struct INI_PAIR *left, *right;        
 45 } ini_pair;
 46 
 47 /*
 48  *    Encapsulates a section within a INI file.
 49  *    Sections are stored in a binary search tree, which attempts (but does not
 50  *    guarantee) O(log(n)) behaviour.
 51  */
 52 typedef struct INI_SECTION
 53 {
 54     char *name;            /* Name of the section */
 55     ini_pair *fields;    /* Fields in the section */
 56     
 57     /* Nodes in the tree */
 58     struct INI_SECTION *left, *right;
 59 } ini_section;
 60 
 61 /*@ struct ##ini_file;
 62  *#    Structure to encapsulate an INI file.
 63  */
 64 struct ini_file
 65 {
 66     ini_pair     *globals;
 67     ini_section *sections;
 68 };
 69 
 70 /*@ ini_file *##ini_read(const char *filename, int *err, int *line);
 71  *#    Reads an INI file named by {{filename}} and returns it as a {{~~ini_file}} object.
 72  *#    If {{filename}} is {{NULL}}, an empty {{ini_file}} object is created and returned.
 73  *#    Comments are discarded, so a later call to {{~~ini_write()}} will be
 74  *#    commentless.\n
 75  *# It returns {{NULL}} if the INI file couldn't be read, in which case {{err}} will contain the error code
 76  *# (see {{~~ini_errstr()}}) and {{line}} will contain the line in the file where the error occured.
 77  *# ({{err}} and {{line}} may be {{NULL}}).
 78  */
 79 struct ini_file *ini_read(const char *filename, int *err, int *line);
 80 
 81 /*@ ini_file *##ini_parse(const char *text, int *err, int *line);
 82  *# Parses a null-terminated string {{text}} as an INI file.\n
 83  *# It returns {{NULL}} if the INI file couldn't be read, in which case {{err}} will contain the error code
 84  *# (see {{~~ini_errstr()}}) and {{line}} will contain the line in the file where the error occured.
 85  *# ({{err}} and {{line}} may be {{NULL}}).
 86  */
 87 struct ini_file *ini_parse(const char *text, int *err, int *line);
 88 
 89 /*@ int ##ini_write(ini_file *ini, const char *fname);
 90  *#    Saves all the sections and parameters in an {{ini_file}} to a file.\n
 91  *#    {{fname}} is the file to which to save. If {{fname}} is {{NULL}}, it is written to 
 92  *#    {{stdout}}.
 93  *# It returns 1 on success, an error code otherwise (see {{~~ini_errstr()}}).
 94  */
 95 int ini_write(struct ini_file *ini, const char *fname);
 96 
 97 /*@ void ##ini_free(ini_file *ini);
 98  *#    Free's all the memory allocated to a {{ini_file}} object created in {{~~ini_read()}}.\n
 99  *#    {{ini}} is the {{ini_file}} to free
100  */
101 void ini_free(struct ini_file *ini);
102 
103 /*@ int ini_has_section(struct ini_file *ini, const char *sec)
104  *# Returns true if the ini file has a specific section.
105  */
106 int ini_has_section(struct ini_file *ini, const char *sec);
107 
108 /*@ const char *##ini_get(struct ini_file *ini, const char *sec, const char *par, const char *def);
109  *#    Retrieves a parameter {{par}} from a section {{sec}} within the struct ini_file {{ini}}
110  *#    and returns its value.\n
111  *#    If {{sec}} is {{NULL}}, the global parameters in {{ini}} are searched.\n
112  *#    If the value is not found, the default {{def}}, which may be {{NULL}}, is 
113  *#    returned.
114  */
115 const char *ini_get(struct ini_file *ini, 
116                     const char *sec, 
117                     const char *par, 
118                     const char *def);
119 
120 /*@ int ##ini_put(struct ini_file *ini, const char *sec, const char *par, const char *val);
121  *#    Sets a parameter {{par}} in section {{sec}}'s value to {{val}}, replacing the 
122  *#    current value if it already exists, or creates the section if it does not 
123  *#    exist.\n
124  *#    If {{sec}} is {{NULL}}, the parameter is added to {{ini}}'s global parameters.\n
125  *# It returns 1 on success, 0 on failure (which only happens if {{malloc()}} fails).
126  */
127 int ini_put(struct ini_file *ini, const char *sec, const char *par, const char *val);
128 
129 /*@ int ##ini_putf(struct ini_file *ini, const char *sec, const char *par, const char *fmt, ...);
130  *#    {{~~ini_putf()}} takes a {{printf()}} style format string and uses vsnprintf() to
131  *#    pass a value to {{~~ini_put()}}. This function is intended for placing 
132  *#    data types that are not strings into the {{ini_file}}
133  *#    
134  *#    The other parameters are the same as those of {{ini_put()}}.
135  */
136 int ini_putf(struct ini_file *ini, 
137             const char *sec, 
138             const char *par, 
139             const char *fmt, 
140             ...);
141 
142 /*@ const char *##ini_errstr(int err)
143  *# Returns a textual description of an error code
144  */
145 const char *ini_errstr(int err);
146             
147 #if defined(__cplusplus)
148 } /* extern "C" */
149 #endif
150 
151 #endif /* INI_H */
ini.h

 

  1 /*
  2  *    This is a simple parser for .INI files.
  3  *    It is based around the syntax described in the Wikipedia entry at
  4  *    "http://en.wikipedia.org/wiki/INI_file"
  5  *
  6  * See ini.h for more info
  7  *
  8  * This is free and unencumbered software released into the public domain.
  9  * http://unlicense.org/
 10  */
 11 #include "stdafx.h"
 12 #include <stdio.h>
 13 #include <stdlib.h>
 14 #include <string.h>
 15 #include <stdarg.h>
 16 #include <ctype.h>
 17 #include <setjmp.h>
 18 
 19 #include <assert.h> /* Remember to define NDEBUG for release */
 20 
 21 #include "ini.h"
 22 #include "utils.h"
 23 #include <crtdbg.h>
 24 
 25 /* Maximum number of characters expected on a line.
 26 It is only used by the ini_putf() function.
 27 */
 28 #define MAX_LINE        1024
 29 
 30 /* Various error codes */
 31 #define SUCCESS                          1
 32 #define FILE_CREATED                  0
 33 #define NO_SUCH_FILE                  -1
 34 #define OUT_OF_MEMORY                  -2
 35 #define MISSING_END_BRACE             -3
 36 #define EMPTY_SECTION                  -4
 37 #define EXPECTED_EQUALS             -5
 38 #define EXPECTED_END_OF_STRING         -6
 39 #define ER_FOPEN                     -7
 40 #define BAD_SYMBOL                     -8
 41 #define EXPECTED_PARAMETER            -9
 42 #define EXPECTED_VALUE                -10
 43 
 44 const char *ini_errstr(int err)
 45 {
 46     switch(err)
 47     {
 48         case SUCCESS : return "Success";
 49         case FILE_CREATED: return "New INI object created";
 50         case NO_SUCH_FILE: return "Unable to open file";
 51         case OUT_OF_MEMORY: return "Out of memory";
 52         case MISSING_END_BRACE: return "Missing ']' at end of section";
 53         case EMPTY_SECTION: return "Empty [] for section";
 54         case EXPECTED_EQUALS : return "Expected an '='/':'";
 55         case EXPECTED_END_OF_STRING : return "Expected an end of string";
 56         case ER_FOPEN : return "Unable to open file";
 57         case BAD_SYMBOL : return "Bad symbol";
 58         case EXPECTED_PARAMETER : return "Expected a parameter (or section)";
 59         case EXPECTED_VALUE : return "Expected a value";
 60     }
 61     return "Unknown";
 62 }
 63 
 64 /** Configurable parameters *************************************************/
 65 
 66 /*
 67  *    Recursively adds sections to the tree of sections
 68  */
 69 static void insert_section(ini_section *r, ini_section *n) {
 70     assert(r);
 71     assert(n);
 72 
 73     if(my_stricmp(r->name, n->name) < 0) {
 74         if(!r->left)
 75             r->left = n;
 76         else
 77             insert_section(r->left, n);
 78     } else {
 79         if(!r->right)
 80             r->right = n;
 81         else
 82             insert_section(r->right, n);
 83     }
 84 }
 85 
 86 /*
 87  *    Searches a tree of pairs for a specific parameter
 88  */
 89 static ini_pair *find_pair(ini_pair *root, const char *name) {
 90     int c;
 91 
 92     if(!root) return NULL;
 93 
 94     c = my_stricmp(root->param, name);
 95     if(c == 0)
 96         return root;
 97     else if(c < 0)
 98         return find_pair(root->left, name);
 99     else
100         return find_pair(root->right, name);
101 }
102 
103 /*
104  *    Searches for a specific section
105  */
106 static ini_section *find_section(ini_section *root, const char *name) {
107     int c;
108 
109     if(!root) return NULL;
110 
111     c = my_stricmp(root->name, name);
112     if(c == 0)
113         return root;
114     else if(c < 0)
115         return find_section(root->left, name);
116     else
117         return find_section(root->right, name);
118 }
119 
120 /*
121  *    Creates a new section, and adds it to a tree of sections
122  */
123 static ini_section *add_section(ini_section **root, char *name) {
124     ini_section *n;
125 
126     assert(root);
127     assert(name);
128 
129     n = find_section(*root, name);
130     if(n) {
131         free(name);
132         return n;
133     }
134 
135     n = (ini_section*)malloc(sizeof *n);
136     if(!n) return NULL;
137 
138     n->name = name;
139 
140     n->fields = NULL;
141     n->left = n->right = NULL;
142 
143     if(*root)
144         insert_section(*root, n);
145     else
146         *root = n;
147 
148     return n;
149 }
150 
151 /*
152  *    Inserts a new pair n into a pair tree p
153  */
154 static void insert_pair(ini_pair *p, ini_pair *n) {
155     if(my_stricmp(p->param, n->param) < 0) {
156         if(!p->left)
157             p->left = n;
158         else
159             insert_pair(p->left, n);
160     } else {
161         if(!p->right)
162             p->right = n;
163         else
164             insert_pair(p->right, n);
165     }
166 }
167 
168 /*
169  *    Adds a parameter-value pair to section s
170  */
171 static ini_pair *add_pair(ini_section *s, char *p, char *v) {
172     ini_pair *n;
173 
174     assert(s);
175 
176     n = (ini_pair*)malloc(sizeof *n);
177     if(!n) return NULL;
178 
179     n->param = p;
180     n->value = v;
181 
182     n->left = n->right = NULL;
183 
184     if(!s->fields)
185         s->fields = n;
186     else
187         insert_pair(s->fields, n);
188 
189     return n;
190 }
191 
192 /** Functions for memory deallocation ***************************************/
193 
194 /*
195  *    Free's a tree of parameter-value pairs
196  */
197 static void free_pair(ini_pair *p) {
198     if(!p) return;
199 
200     free_pair(p->left);
201     free_pair(p->right);
202 
203     free(p->param);
204     free(p->value);
205     free(p);
206 }
207 
208 /*
209  *    Free's all the memory allocated to a ini_section s
210  */
211 static void free_section(ini_section *s) {
212     if(!s) return;
213 
214     free_section(s->left);
215     free_section(s->right);
216 
217     free(s->name);
218     free_pair(s->fields);
219     free(s);
220 }
221 
222 /*
223  *    Free's all the memory allocated to a ini_file object in ini_read()
224  */
225 void ini_free(struct ini_file *ini) {
226     if(!ini) return;
227     free_pair(ini->globals);
228     free_section(ini->sections);
229     free(ini);
230 }
231 
232 /** Parsing functions *******************************************************/
233 
234 static struct ini_file *make_ini() 
235 {
236     struct ini_file *ini = (ini_file*)malloc(sizeof *ini);
237     if(!ini) return NULL;
238     ini->globals = NULL;
239     ini->sections = NULL;
240     return ini;
241 }
242 
243 /*
244  *    Reads an INI file and returns it as a ini_file object.
245  *    If filename is NULL, an empty ini_file object is created and returned.
246  */
247 struct ini_file *ini_read(const char *filename, int *err, int *line) {
248     if(line) *line = 0;
249     if(!filename)
250     {
251         if(err) *err = FILE_CREATED;
252         return make_ini();
253     } 
254     else 
255     {
256         char *text = my_readfile(filename);
257         if(!text) {
258             if(err) *err = NO_SUCH_FILE;
259             return NULL;
260         }
261         struct ini_file * ini = ini_parse(text, err, line);
262         free(text);
263         return ini;
264     }
265 }
266 
267 #define T_END        0
268 #define T_VALUE        1
269 
270 static int get_token(const char **tp, const char **tstart, const char **tend, int *line, jmp_buf err) {
271     /* *tstart points to the start of the token, while *tend points one char past the end */
272 
273     const char *t = *tp;
274     int tok = T_END;
275 
276     assert(tp && tstart && tend);
277 
278 whitespace:
279     while(isspace(t[0])) {
280         if(t[0] == '\n' && line)
281             (*line)++;
282         t++;
283     }
284     if(t[0] == ';' || t[0] == '#') {
285         while(t[0] != '\n' && t[0] != '\0')
286             t++;
287         goto whitespace;
288     }
289 
290     *tstart = t;
291     *tend = t;
292     if(t[0]) {
293         if(strchr("[]:=", t[0])) {
294             tok = *t++;
295         } else if(isgraph(t[0]) && !strchr("\"'[];#", t[0])) {
296             while(isgraph(t[0]) && !strchr("\"'[];#", t[0])) {
297                 t++;
298             }
299             *tend = t;
300             tok = T_VALUE;
301         } else if(t[0] == '\"' || t[0] == '\'') {
302             char delim = t[0];
303             if(t[1] == delim && t[2] == delim) {
304                 /* """Python style long strings""" */
305                 t += 3;
306                 *tstart = t;
307                 while(!(t[0] == delim && t[1] == delim && t[2] == delim)) {
308                     if(t[0] == '\0') {
309                         longjmp(err, EXPECTED_END_OF_STRING);
310                     } else if(t[0] == '\\')
311                         t++;
312                     t++;
313                 }
314                 *tend = t;
315                 t+=3;
316             } else {
317                 *tstart = ++t;
318                 while(t[0] != delim) {
319                     if(t[0] == '\0' || t[0] == '\n') {
320                         longjmp(err, EXPECTED_END_OF_STRING);
321                     } else if(t[0] == '\\')
322                         t++;
323                     t++;
324                 }
325                 *tend = t++;
326             }
327             tok = T_VALUE;
328         } else {
329             /* Unrecognized token */
330             longjmp(err, BAD_SYMBOL);
331         }
332     }
333 
334     *tp = t;
335     return tok;
336 }
337 
338 static char *get_string(const char *tstart, const char *tend, jmp_buf err) 
339 {
340     char *string, *s;
341     const char *i;
342 
343     assert(tend > tstart);
344     string = (char*)malloc(tend - tstart + 1);
345     if(!string)
346         longjmp(err, OUT_OF_MEMORY);
347 
348     for(i = tstart, s = string; i < tend; i++) {
349         if(i[0] == '\\') {
350             switch(*++i) {
351                 case '\\':
352                 case '\'':
353                 case '\"': *s++ = i[0]; break;
354                 case 'r': *s++ = '\r'; break;
355                 case 'n': *s++ = '\n'; break;
356                 case 't': *s++ = '\t'; break;
357                 case '0': *s++ = '\0'; break;
358                 default: break;
359             }
360         } else {
361             *s++ = i[0];
362         }
363     }
364     assert(s - string <= tend - tstart);
365     s[0] = '\0';
366     return string;
367 }
368 
369 struct ini_file *ini_parse(const char *text, int *err, int *line) {
370     jmp_buf on_error;
371     int e_code;
372 
373     struct ini_file *ini = NULL;
374     ini_section *cur_sec = NULL;
375 
376     const char *tstart, *tend;
377 
378     int t;
379 
380     if(err) *err = SUCCESS;
381     if(line) *line = 1;
382 
383     ini = make_ini();
384 
385     if((e_code = setjmp(on_error)) != 0) {
386         if(err) *err = e_code;
387         ini_free(ini);
388         return NULL;
389     }
390 
391     while((t = get_token(&text, &tstart, &tend, line, on_error)) != T_END) {
392         if(t == '[') {
393             char *section_name;
394             if(get_token(&text, &tstart, &tend, line, on_error) != T_VALUE) {
395                 longjmp(on_error, EMPTY_SECTION);
396             }
397 
398             section_name = get_string(tstart, tend, on_error);
399 
400             cur_sec = add_section(&ini->sections, section_name);
401             if(!cur_sec)
402                 longjmp(on_error, OUT_OF_MEMORY);
403 
404             if(get_token(&text, &tstart, &tend, line, on_error) != ']') {
405                 longjmp(on_error, MISSING_END_BRACE);
406             }
407 
408         } else if (t == T_VALUE ) {
409             char *par, *val;
410             par = get_string(tstart, tend, on_error);
411             t = get_token(&text, &tstart, &tend, line, on_error);
412             if(t != '=' && t != ':') {
413                 longjmp(on_error, EXPECTED_EQUALS);
414             }
415             if(get_token(&text, &tstart, &tend, line, on_error) != T_VALUE) {
416                 longjmp(on_error, EXPECTED_VALUE);
417             }
418             val = get_string(tstart, tend, on_error);
419 
420             if(cur_sec)
421                 add_pair(cur_sec, par, val);
422             else {
423                 /* Add the parameter and value to the INI file's globals */
424                 ini_pair *pair;
425                 if(!(pair = (ini_pair*)malloc(sizeof *pair)))
426                     longjmp(on_error, OUT_OF_MEMORY);
427 
428                 pair->param = par;
429                 pair->value = val;
430 
431                 pair->left = pair->right = NULL;
432 
433                 if(!ini->globals)
434                     ini->globals = pair;
435                 else
436                     insert_pair(ini->globals, pair);
437             }
438 
439 
440         } else
441             longjmp(on_error, EXPECTED_PARAMETER);
442     }
443 
444     return ini;
445 }
446 
447 /** Printing functions ******************************************************/
448 
449 static void string_to_file(FILE *f, const char *s) {
450     fputc('\"', f);
451     for(; s[0]; s++) {
452         switch(s[0]) {
453             case '\n': fputs("\\n",f); break;
454             case '\r': fputs("\\r",f); break;
455             case '\t': fputs("\\t",f); break;
456             case '\"': fputs("\\\"",f); break;
457             case '\'': fputs("\\\'",f); break;
458             case '\\': fputs("\\\\",f); break;
459             default : fputc(s[0], f); break;
460         }
461     }
462     fputc('\"', f);
463 }
464 
465 /*
466  *    Recursively prints a tree of ini_pairs
467  */
468 static void write_pair(ini_pair *p, FILE *f) {
469     if(!p) return;
470 
471     string_to_file(f, p->param);
472     fputs(" = ", f);
473     string_to_file(f, p->value);
474     fputc('\n', f);
475 
476     write_pair(p->left, f);
477     write_pair(p->right, f);
478 }
479 
480 /*
481  *    Recursively prints a tree of INI sections
482  */
483 static void write_section(ini_section *s, FILE *f) {
484     if(!s) return;
485 
486     fputs("\n[", f);
487     string_to_file(f, s->name);
488     fputs("]\n", f);
489 
490     write_pair(s->fields, f);
491 
492     /* The akward sequence is to ensure that values are not written sorted */
493 
494     write_section(s->left, f);
495     write_section(s->right, f);
496 }
497 
498 /*
499  *    Saves all the sections and parameters in an ini_file to a file.
500  *    If fname is NULL, it is written to stdout.
501  */
502 int ini_write(struct ini_file *ini, const char *fname) {
503     FILE *f;
504 
505     if(fname) {
506         f = fopen(fname, "w");
507         if(!f)
508             return ER_FOPEN;
509     } else
510         f = stdout;
511 
512     write_pair(ini->globals, f);
513     write_section(ini->sections, f);
514 
515     if(fname)
516         fclose(f);
517 
518     return SUCCESS;
519 }
520 
521 /****************************************************************************/
522 
523 int ini_has_section(struct ini_file *ini, const char *sec) {
524     return find_section(ini->sections, sec) != NULL;
525 }
526 
527 /*
528  *    Finds a specific parameter-value pair in the configuration file
529  */
530 static ini_pair *find_param(const struct ini_file *ini,
531                             const char *sec,
532                             const char *par) {
533     ini_section *s;
534     ini_pair *p;
535 
536     if(!ini) return NULL;
537 
538     if(sec) {
539         s = find_section(ini->sections, sec);
540         if(!s) return NULL;
541         p = s->fields;
542     } else
543         p = ini->globals;
544 
545     if(!p) return NULL;
546 
547     return find_pair(p, par);
548 }
549 
550 /*
551  *    Retrieves a parameter 'par' from a section 'sec' within the ini_file 'ini'
552  *    and returns its value.
553  *    If 'sec' is NULL, the global parameters ini 'ini' are searched.
554  *    If the value is not found, 'def' is returned.
555  *    It returns a string. Functions like atoi(), atof(), strtol() and even
556  *    sscanf() can be used to convert it to the relevant type.
557  */
558 const char *ini_get(struct ini_file *ini,
559                     const char *sec,
560                     const char *par,
561                     const char *def) {
562     ini_pair *p;
563 
564     p = find_param(ini, sec, par);
565     if(!p) {
566         if(def)
567             ini_put(ini, sec, par, def);
568         return def;
569     }
570 
571     return p->value;
572 }
573 
574 /*
575  *    Sets a parameter 'par' in section 'sec's value to 'val', replacing the
576  *    current value if it already exists, or creates the section if it does not
577  *    exist
578  */
579 int ini_put(struct ini_file *ini, const char *sec, const char *par, const char *val) {
580     ini_section *s;
581     ini_pair *p, **pp;
582 
583     if(!ini || !val) return 0;
584 
585     p = find_param(ini, sec, par);
586     if(p) {
587         /* Replace the existing value */
588         char *t = p->value;
589         if(!(p->value = my_strdup(val))) {
590             p->value = t;
591             return 0;
592         }
593 
594         free(t);
595         return 1;
596     }
597 
598     if(sec) {
599         s = find_section(ini->sections, sec);
600         if(!s) {
601             /* Create a new section */
602             if(!(s = (ini_section*)malloc(sizeof *s))) return 0;
603             if(!(s->name = my_strdup(sec))) {
604                 free(s);
605                 return 0;
606             }
607 
608             s->fields = NULL;
609             s->left = s->right = NULL;
610 
611             if(ini->sections)
612                 insert_section(ini->sections, s);
613             else
614                 ini->sections = s;
615         }
616 
617         pp = &s->fields;
618     } else
619         pp = &ini->globals;
620 
621     if(!(p = (ini_pair*)malloc(sizeof *p)))
622         return 0;
623 
624     if(!(p->param = my_strdup(par)) || !(p->value = my_strdup(val))) {
625         free(p);
626         return 0;
627     }
628 
629     p->left = p->right = NULL;
630 
631     if(!*pp)
632         *pp = p;
633     else
634         insert_pair(*pp, p);
635 
636     return 1;
637 }
638 
639 /*
640  *    ini_putf() takes a printf() style format string and uses vsnprintf() to
641  *    pass a value to ini_put(). This function is intended for placing
642  *    data types that are not strings into the ini_file
643  *
644  *    The other parameters are the same as those of ini_put().
645  */
646 int ini_putf(struct ini_file *ini,
647             const char *sec,
648             const char *par,
649             const char *fmt,
650             ...) {
651     char buffer[MAX_LINE];
652     va_list arg;
653 
654     va_start(arg, fmt);
655 
656 #ifdef _MSC_VER /* Microsoft Visual C++? */
657     /* VC++ messes around with _'s before vsnprintf(): */
658 #define    vsnprintf _vsnprintf
659 #endif
660 
661 #if 1
662     vsnprintf(buffer, MAX_LINE, fmt, arg);
663 #else
664     vsprintf(buffer, fmt, arg );
665     assert(strlen(buffer) < MAX_LINE);
666 #endif
667     va_end(arg);
668 
669     return ini_put(ini, sec, par, buffer);
670 }
ini.cpp

调用

  1 static struct ini_file *gamedb = NULL;
  2 BOOL CRobomoduleTestDlg::ResetConfig()
  3 {
  4     ini_put(gamedb, "System", "Half", "0");
  5     ini_put(gamedb, "InitialPose", "X", "0.0");
  6     ini_put(gamedb, "InitialPose", "Y", "0.0");
  7     ini_put(gamedb, "InitialPose", "theta", "0.0");
  8 
  9     ini_put(gamedb, "TilingUnit_Pose", "XTrans", "0.0");
 10     ini_put(gamedb, "TilingUnit_Pose", "YTrans", "0.0");
 11     ini_put(gamedb, "TilingUnit_Pose", "Height", "1.10");
 12 
 13     ini_put(gamedb, "Laser_TilingUnitO", "RotateX", "0.0");
 14     ini_put(gamedb, "Laser_TilingUnitO", "RotateY", "0.0");
 15     ini_put(gamedb, "Laser_TilingUnitO", "RotateZ", "0.785398163");
 16 
 17     ini_put(gamedb, "Laser_TilingUnitO", "TransformX", "0.165");
 18     ini_put(gamedb, "Laser_TilingUnitO", "TransformY", "0.0");
 19     ini_put(gamedb, "Laser_TilingUnitO", "TransformZ", "0.0");
 20 
 21     ini_put(gamedb, "LaserO", "CalibRotateX", "-0.023289177");
 22     ini_put(gamedb, "LaserO", "CalibRotateY", "0.0");
 23     ini_put(gamedb, "LaserO", "CalibRotateZ", "-0.01573419");
 24 
 25     ini_put(gamedb, "LaserO", "CalibTransformX", "0.0");
 26     ini_put(gamedb, "LaserO", "CalibTransformY", "0.0");
 27     ini_put(gamedb, "LaserO", "CalibTransformZ", "0.0");
 28 
 29     char buffer[256];
 30     _snprintf(buffer, sizeof buffer, "%s/%s", "D:", "config.ini");
 31 
 32     int result = ini_write(gamedb,"config.ini");
 33     ini_free(gamedb);
 34 
 35     gamedb=NULL    ;
 36     return TRUE;
 37 }
 38 
 39 BOOL CRobomoduleTestDlg::OnInitDialog()
 40 {
 41     CDialog::OnInitDialog();
 42     ini_free(gamedb);
 43     gamedb = ini_read(NULL, NULL, NULL);
 44     int err, line;
 45     ini_free(gamedb);
 46     gamedb = ini_read("config.ini", &err, &line);
 47     if(ini_get(gamedb,"InitialPose", "X", NULL) != NULL) 
 48     {
 49         const char* a=ini_get(gamedb, "InitialPose", "X", NULL);
 50         InitialPoseX= atof(a);
 51     }
 52     if(ini_get(gamedb,"InitialPose", "Y", NULL) != NULL) 
 53     {
 54         const char* a=ini_get(gamedb, "InitialPose", "Y", NULL);
 55         InitialPoseY= atof(a);
 56     }
 57     if(ini_get(gamedb,"InitialPose", "theta", NULL) != NULL) 
 58     {
 59         const char* a=ini_get(gamedb, "InitialPose", "theta", NULL);
 60         InitialPoseTheta= atof(a);
 61     }
 62     if(ini_get(gamedb,"TilingUnit_Pose", "XTrans", NULL) != NULL) 
 63     {
 64         const char* a=ini_get(gamedb, "TilingUnit_Pose", "XTrans", NULL);
 65         XTrans= atof(a);
 66     }
 67     if(ini_get(gamedb,"TilingUnit_Pose", "YTrans", NULL) != NULL) 
 68     {
 69         const char* a=ini_get(gamedb, "TilingUnit_Pose", "YTrans", NULL);
 70         YTrans= atof(a);
 71     }
 72     if(ini_get(gamedb,"TilingUnit_Pose", "Height", NULL) != NULL) 
 73     {
 74         const char* a=ini_get(gamedb, "TilingUnit_Pose", "Height", NULL);
 75         Height= atof(a);
 76     }
 77     if(ini_get(gamedb,"Laser_TilingUnitO", "RotateX", NULL) != NULL) 
 78     {
 79         const char* b=ini_get(gamedb, "Laser_TilingUnitO", "RotateX", NULL);
 80         RotateX= atof(b);
 81     }
 82     if(ini_get(gamedb,"Laser_TilingUnitO", "RotateY", NULL) != NULL) 
 83     {
 84         const char* a=ini_get(gamedb, "Laser_TilingUnitO", "RotateY", NULL);
 85         RotateY= atof(a);
 86     }
 87     if(ini_get(gamedb,"Laser_TilingUnitO", "RotateZ", NULL) != NULL) 
 88     {
 89         const char* a=ini_get(gamedb, "Laser_TilingUnitO", "RotateZ", NULL);
 90         RotateZ= atof(a);
 91     }
 92     if(ini_get(gamedb,"Laser_TilingUnitO", "TransformX", NULL) != NULL) 
 93     {
 94         const char* a=ini_get(gamedb, "Laser_TilingUnitO", "TransformX", NULL);
 95         TransformX= atof(a);
 96     }
 97     if(ini_get(gamedb,"Laser_TilingUnitO", "TransformY", NULL) != NULL) 
 98     {
 99         const char* a=ini_get(gamedb, "Laser_TilingUnitO", "TransformY", NULL);
100         TransformY= atof(a);
101     }
102     if(ini_get(gamedb,"Laser_TilingUnitO", "TransformZ", NULL) != NULL) 
103     {
104         const char* a=ini_get(gamedb, "Laser_TilingUnitO", "TransformZ", NULL);
105         TransformZ= atof(a);
106     }
107     if(ini_get(gamedb,"LaserO", "CalibRotateX", NULL) != NULL) 
108     {
109         const char* a=ini_get(gamedb, "LaserO", "CalibRotateX", NULL);
110         CalibRotateX= atof(a);
111     }
112     if(ini_get(gamedb,"LaserO", "CalibRotateY", NULL) != NULL) 
113     {
114         const char* a=ini_get(gamedb, "LaserO", "CalibRotateY", NULL);
115         CalibRotateY= atof(a);
116     }
117     if(ini_get(gamedb,"LaserO", "CalibRotateZ", NULL) != NULL) 
118     {
119         const char* a=ini_get(gamedb, "LaserO", "CalibRotateZ", NULL);
120         CalibRotateZ= atof(a);
121     }
122     if(ini_get(gamedb,"LaserO", "CalibTransformX", NULL) != NULL) 
123     {
124         const char* a=ini_get(gamedb, "LaserO", "CalibTransformX", NULL);
125         CalibTransformX= atof(a);
126     }
127     if(ini_get(gamedb,"LaserO", "CalibTransformY", NULL) != NULL) 
128     {
129         const char* a=ini_get(gamedb, "LaserO", "CalibTransformY", NULL);
130         CalibTransformY= atof(a);
131     }
132     if(ini_get(gamedb,"LaserO", "CalibTransformZ", NULL) != NULL) 
133     {
134         const char* a=ini_get(gamedb, "LaserO", "CalibTransformZ", NULL);
135         CalibTransformZ= atof(a);
136     }
137     if(ini_get(gamedb,"System", "Half", NULL) != NULL) 
138     {
139         const char* a=ini_get(gamedb, "System", "Half", NULL);
140         useHalf= atof(a);
141     }

 参考:https://github.com/wernsey/rengine/blob/master/src/ini.c

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值