首页 > 代码库 > C语言ini格式配置文件的读写
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 API13 */14 #include "stdafx.h"15 /*@ MY_MIN(a,b)16 *# Macro that returns the smallest of its parameters.\n17 *# 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.\n23 *# 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.\n37 *# The returned buffer needs to be {{free()}}d after use. It may return38 *# {{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.\n61 *# The returned buffer needs to be {{free()}}d afterwards.\n62 *# It returns {{NULL}} if the file could not be read.63 */64 char *my_readfile (const char *fn);
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 afterwards69 */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 }
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 free100 */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.\n111 *# If {{sec}} is {{NULL}}, the global parameters in {{ini}} are searched.\n112 *# 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.\n124 *# If {{sec}} is {{NULL}}, the parameter is added to {{ini}}‘s global parameters.\n125 *# 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() to131 *# 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 code144 */145 const char *ini_errstr(int err);146 147 #if defined(__cplusplus)148 } /* extern "C" */149 #endif150 151 #endif /* 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 else100 return find_pair(root->right, name);101 }102 103 /*104 * Searches for a specific section105 */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 else117 return find_section(root->right, name);118 }119 120 /*121 * Creates a new section, and adds it to a tree of sections122 */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 else146 *root = n;147 148 return n;149 }150 151 /*152 * Inserts a new pair n into a pair tree p153 */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 else159 insert_pair(p->left, n);160 } else {161 if(!p->right)162 p->right = n;163 else164 insert_pair(p->right, n);165 }166 }167 168 /*169 * Adds a parameter-value pair to section s170 */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 =http://www.mamicode.com/ v;181 182 n->left = n->right = NULL;183 184 if(!s->fields)185 s->fields = n;186 else187 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 pairs196 */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 s210 */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 0268 #define T_VALUE 1269 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 =http://www.mamicode.com/ val;430 431 pair->left = pair->right = NULL;432 433 if(!ini->globals)434 ini->globals = pair;435 else436 insert_pair(ini->globals, pair);437 }438 439 440 } else441 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_pairs467 */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 sections482 */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 } else510 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 file529 */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 } else543 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 even556 * 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 the576 * current value if it already exists, or creates the section if it does not577 * exist578 */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 =http://www.mamicode.com/ my_strdup(val))) {590 p->value =http://www.mamicode.com/ 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 else614 ini->sections = s;615 }616 617 pp = &s->fields;618 } else619 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 =http://www.mamicode.com/ 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 else634 insert_pair(*pp, p);635 636 return 1;637 }638 639 /*640 * ini_putf() takes a printf() style format string and uses vsnprintf() to641 * pass a value to ini_put(). This function is intended for placing642 * data types that are not strings into the ini_file643 *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 _vsnprintf659 #endif660 661 #if 1662 vsnprintf(buffer, MAX_LINE, fmt, arg);663 #else664 vsprintf(buffer, fmt, arg );665 assert(strlen(buffer) < MAX_LINE);666 #endif667 va_end(arg);668 669 return ini_put(ini, sec, par, buffer);670 }
调用
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
C语言ini格式配置文件的读写
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。