您的位置:首页 > 编程语言 > C语言/C++

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

2017-03-29 15:10 411 查看
依赖的类

/*
*    This is a simple parser for .INI files.
*    It is based around the syntax described in the Wikipedia entry at
*    "http://en.wikipedia.org/wiki/INI_file"
*
* See ini.h for more info
*
* This is free and unencumbered software released into the public domain.
* http://unlicense.org/ */
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
#include <setjmp.h>

#include <assert.h> /* Remember to define NDEBUG for release */

#include "ini.h"
#include "utils.h"
#include <crtdbg.h>

/* Maximum number of characters expected on a line.
It is only used by the ini_putf() function.
*/
#define MAX_LINE        1024

/* Various error codes */
#define SUCCESS                          1
#define FILE_CREATED                  0
#define NO_SUCH_FILE                  -1
#define OUT_OF_MEMORY                  -2
#define MISSING_END_BRACE             -3
#define EMPTY_SECTION                  -4
#define EXPECTED_EQUALS             -5
#define EXPECTED_END_OF_STRING         -6
#define ER_FOPEN                     -7
#define BAD_SYMBOL                     -8
#define EXPECTED_PARAMETER            -9
#define EXPECTED_VALUE                -10

const char *ini_errstr(int err)
{
switch(err)
{
case SUCCESS : return "Success";
case FILE_CREATED: return "New INI object created";
case NO_SUCH_FILE: return "Unable to open file";
case OUT_OF_MEMORY: return "Out of memory";
case MISSING_END_BRACE: return "Missing ']' at end of section";
case EMPTY_SECTION: return "Empty [] for section";
case EXPECTED_EQUALS : return "Expected an '='/':'";
case EXPECTED_END_OF_STRING : return "Expected an end of string";
case ER_FOPEN : return "Unable to open file";
case BAD_SYMBOL : return "Bad symbol";
case EXPECTED_PARAMETER : return "Expected a parameter (or section)";
case EXPECTED_VALUE : return "Expected a value";
}
return "Unknown";
}

/** Configurable parameters *************************************************/

/*
*    Recursively adds sections to the tree of sections
*/
static void insert_section(ini_section *r, ini_section *n) {
assert(r);
assert(n);

if(my_stricmp(r->name, n->name) < 0) {
if(!r->left)
r->left = n;
else
insert_section(r->left, n);
} else {
if(!r->right)
r->right = n;
else
insert_section(r->right, n);
}
}

/*
*    Searches a tree of pairs for a specific parameter
*/
static ini_pair *find_pair(ini_pair *root, const char *name) {
int c;

if(!root) return NULL;

c = my_stricmp(root->param, name);
if(c == 0)
return root;
else if(c < 0)
return find_pair(root->left, name);
else
return find_pair(root->right, name);
}

/*
*    Searches for a specific section
*/
static ini_section *find_section(ini_section *root, const char *name) {
int c;

if(!root) return NULL;

c = my_stricmp(root->name, name);
if(c == 0)
return root;
else if(c < 0)
return find_section(root->left, name);
else
return find_section(root->right, name);
}

/*
*    Creates a new section, and adds it to a tree of sections
*/
static ini_section *add_section(ini_section **root, char *name) {
ini_section *n;

assert(root);
assert(name);

n = find_section(*root, name);
if(n) {
free(name);
return n;
}

n = (ini_section*)malloc(sizeof *n);
if(!n) return NULL;

n->name = name;

n->fields = NULL;
n->left = n->right = NULL;

if(*root)
insert_section(*root, n);
else
*root = n;

return n;
}

/*
*    Inserts a new pair n into a pair tree p
*/
static void insert_pair(ini_pair *p, ini_pair *n) {
if(my_stricmp(p->param, n->param) < 0) {
if(!p->left)
p->left = n;
else
insert_pair(p->left, n);
} else {
if(!p->right)
p->right = n;
else
insert_pair(p->right, n);
}
}

/*
*    Adds a parameter-value pair to section s
*/
static ini_pair *add_pair(ini_section *s, char *p, char *v) {
ini_pair *n;

assert(s);

n = (ini_pair*)malloc(sizeof *n);
if(!n) return NULL;

n->param = p;
n->value = v;

n->left = n->right = NULL;

if(!s->fields)
s->fields = n;
else
insert_pair(s->fields, n);

return n;
}

/** Functions for memory deallocation ***************************************/

/*
*    Free's a tree of parameter-value pairs
*/
static void free_pair(ini_pair *p) {
if(!p) return;

free_pair(p->left);
free_pair(p->right);

free(p->param);
free(p->value);
free(p);
}

/*
*    Free's all the memory allocated to a ini_section s
*/
static void free_section(ini_section *s) {
if(!s) return;

free_section(s->left);
free_section(s->right);

free(s->name);
free_pair(s->fields);
free(s);
}

/*
*    Free's all the memory allocated to a ini_file object in ini_read()
*/
void ini_free(struct ini_file *ini) {
if(!ini) return;
free_pair(ini->globals);
free_section(ini->sections);
free(ini);
}

/** Parsing functions *******************************************************/

static struct ini_file *make_ini()
{
struct ini_file *ini = (ini_file*)malloc(sizeof *ini);
if(!ini) return NULL;
ini->globals = NULL;
ini->sections = NULL;
return ini;
}

/*
*    Reads an INI file and returns it as a ini_file object.
*    If filename is NULL, an empty ini_file object is created and returned.
*/
struct ini_file *ini_read(const char *filename, int *err, int *line) {
if(line) *line = 0;
if(!filename)
{
if(err) *err = FILE_CREATED;
return make_ini();
}
else
{
char *text = my_readfile(filename);
if(!text) {
if(err) *err = NO_SUCH_FILE;
return NULL;
}
struct ini_file * ini = ini_parse(text, err, line);
free(text);
return ini;
}
}

#define T_END        0
#define T_VALUE        1

static int get_token(const char **tp, const char **tstart, const char **tend, int *line, jmp_buf err) {
/* *tstart points to the start of the token, while *tend points one char past the end */

const char *t = *tp;
int tok = T_END;

assert(tp && tstart && tend);

whitespace:
while(isspace(t[0])) {
if(t[0] == '\n' && line)
(*line)++;
t++;
}
if(t[0] == ';' || t[0] == '#') {
while(t[0] != '\n' && t[0] != '\0')
t++;
goto whitespace;
}

*tstart = t;
*tend = t;
if(t[0]) {
if(strchr("[]:=", t[0])) {
tok = *t++;
} else if(isgraph(t[0]) && !strchr("\"'[];#", t[0])) {
while(isgraph(t[0]) && !strchr("\"'[];#", t[0])) {
t++;
}
*tend = t;
tok = T_VALUE;
} else if(t[0] == '\"' || t[0] == '\'') {
char delim = t[0];
if(t[1] == delim && t[2] == delim) {
/* """Python style long strings""" */
t += 3;
*tstart = t;
while(!(t[0] == delim && t[1] == delim && t[2] == delim)) {
if(t[0] == '\0') {
longjmp(err, EXPECTED_END_OF_STRING);
} else if(t[0] == '\\')
t++;
t++;
}
*tend = t;
t+=3;
} else {
*tstart = ++t;
while(t[0] != delim) {
if(t[0] == '\0' || t[0] == '\n') {
longjmp(err, EXPECTED_END_OF_STRING);
} else if(t[0] == '\\')
t++;
t++;
}
*tend = t++;
}
tok = T_VALUE;
} else {
/* Unrecognized token */
longjmp(err, BAD_SYMBOL);
}
}

*tp = t;
return tok;
}

static char *get_string(const char *tstart, const char *tend, jmp_buf err)
{
char *string, *s;
const char *i;

assert(tend > tstart);
string = (char*)malloc(tend - tstart + 1);
if(!string)
longjmp(err, OUT_OF_MEMORY);

for(i = tstart, s = string; i < tend; i++) {
if(i[0] == '\\') {
switch(*++i) {
case '\\':
case '\'':
case '\"': *s++ = i[0]; break;
case 'r': *s++ = '\r'; break;
case 'n': *s++ = '\n'; break;
case 't': *s++ = '\t'; break;
case '0': *s++ = '\0'; break;
default: break;
}
} else {
*s++ = i[0];
}
}
assert(s - string <= tend - tstart);
s[0] = '\0';
return string;
}

struct ini_file *ini_parse(const char *text, int *err, int *line) {
jmp_buf on_error;
int e_code;

struct ini_file *ini = NULL;
ini_section *cur_sec = NULL;

const char *tstart, *tend;

int t;

if(err) *err = SUCCESS;
if(line) *line = 1;

ini = make_ini();

if((e_code = setjmp(on_error)) != 0) {
if(err) *err = e_code;
ini_free(ini);
return NULL;
}

while((t = get_token(&text, &tstart, &tend, line, on_error)) != T_END) {
if(t == '[') {
char *section_name;
if(get_token(&text, &tstart, &tend, line, on_error) != T_VALUE) {
longjmp(on_error, EMPTY_SECTION);
}

section_name = get_string(tstart, tend, on_error);

cur_sec = add_section(&ini->sections, section_name);
if(!cur_sec)
longjmp(on_error, OUT_OF_MEMORY);

if(get_token(&text, &tstart, &tend, line, on_error) != ']') {
longjmp(on_error, MISSING_END_BRACE);
}

} else if (t == T_VALUE ) {
char *par, *val;
par = get_string(tstart, tend, on_error);
t = get_token(&text, &tstart, &tend, line, on_error);
if(t != '=' && t != ':') {
longjmp(on_error, EXPECTED_EQUALS);
}
if(get_token(&text, &tstart, &tend, line, on_error) != T_VALUE) {
longjmp(on_error, EXPECTED_VALUE);
}
val = get_string(tstart, tend, on_error);

if(cur_sec)
add_pair(cur_sec, par, val);
else {
/* Add the parameter and value to the INI file's globals */
ini_pair *pair;
if(!(pair = (ini_pair*)malloc(sizeof *pair)))
longjmp(on_error, OUT_OF_MEMORY);

pair->param = par;
pair->value = val;

pair->left = pair->right = NULL;

if(!ini->globals)
ini->globals = pair;
else
insert_pair(ini->globals, pair);
}

} else
longjmp(on_error, EXPECTED_PARAMETER);
}

return ini;
}

/** Printing functions ******************************************************/

static void string_to_file(FILE *f, const char *s) {
fputc('\"', f);
for(; s[0]; s++) {
switch(s[0]) {
case '\n': fputs("\\n",f); break;
case '\r': fputs("\\r",f); break;
case '\t': fputs("\\t",f); break;
case '\"': fputs("\\\"",f); break;
case '\'': fputs("\\\'",f); break;
case '\\': fputs("\\\\",f); break;
default : fputc(s[0], f); break;
}
}
fputc('\"', f);
}

/*
*    Recursively prints a tree of ini_pairs
*/
static void write_pair(ini_pair *p, FILE *f) {
if(!p) return;

string_to_file(f, p->param);
fputs(" = ", f);
string_to_file(f, p->value);
fputc('\n', f);

write_pair(p->left, f);
write_pair(p->right, f);
}

/*
*    Recursively prints a tree of INI sections
*/
static void write_section(ini_section *s, FILE *f) {
if(!s) return;

fputs("\n[", f);
string_to_file(f, s->name);
fputs("]\n", f);

write_pair(s->fields, f);

/* The akward sequence is to ensure that values are not written sorted */

write_section(s->left, f);
write_section(s->right, f);
}

/*
*    Saves all the sections and parameters in an ini_file to a file.
*    If fname is NULL, it is written to stdout.
*/
int ini_write(struct ini_file *ini, const char *fname) {
FILE *f;

if(fname) {
f = fopen(fname, "w");
if(!f)
return ER_FOPEN;
} else
f = stdout;

write_pair(ini->globals, f);
write_section(ini->sections, f);

if(fname)
fclose(f);

return SUCCESS;
}

/****************************************************************************/

int ini_has_section(struct ini_file *ini, const char *sec) {
return find_section(ini->sections, sec) != NULL;
}

/*
*    Finds a specific parameter-value pair in the configuration file
*/
static ini_pair *find_param(const struct ini_file *ini,
const char *sec,
const char *par) {
ini_section *s;
ini_pair *p;

if(!ini) return NULL;

if(sec) {
s = find_section(ini->sections, sec);
if(!s) return NULL;
p = s->fields;
} else
p = ini->globals;

if(!p) return NULL;

return find_pair(p, par);
}

/*
*    Retrieves a parameter 'par' from a section 'sec' within the ini_file 'ini'
*    and returns its value.
*    If 'sec' is NULL, the global parameters ini 'ini' are searched.
*    If the value is not found, 'def' is returned.
*    It returns a string. Functions like atoi(), atof(), strtol() and even
*    sscanf() can be used to convert it to the relevant type.
*/
const char *ini_get(struct ini_file *ini,
const char *sec,
const char *par,
const char *def) {
ini_pair *p;

p = find_param(ini, sec, par);
if(!p) {
if(def)
ini_put(ini, sec, par, def);
return def;
}

return p->value;
}

/*
*    Sets a parameter 'par' in section 'sec's value to 'val', replacing the
*    current value if it already exists, or creates the section if it does not
*    exist
*/
int ini_put(struct ini_file *ini, const char *sec, const char *par, const char *val) {
ini_section *s;
ini_pair *p, **pp;

if(!ini || !val) return 0;

p = find_param(ini, sec, par);
if(p) {
/* Replace the existing value */
char *t = p->value;
if(!(p->value = my_strdup(val))) {
p->value = t;
return 0;
}

free(t);
return 1;
}

if(sec) {
s = find_section(ini->sections, sec);
if(!s) {
/* Create a new section */
if(!(s = (ini_section*)malloc(sizeof *s))) return 0;
if(!(s->name = my_strdup(sec))) {
free(s);
return 0;
}

s->fields = NULL;
s->left = s->right = NULL;

if(ini->sections)
insert_section(ini->sections, s);
else
ini->sections = s;
}

pp = &s->fields;
} else
pp = &ini->globals;

if(!(p = (ini_pair*)malloc(sizeof *p)))
return 0;

if(!(p->param = my_strdup(par)) || !(p->value = my_strdup(val))) {
free(p);
return 0;
}

p->left = p->right = NULL;

if(!*pp)
*pp = p;
else
insert_pair(*pp, p);

return 1;
}

/*
*    ini_putf() takes a printf() style format string and uses vsnprintf() to
*    pass a value to ini_put(). This function is intended for placing
*    data types that are not strings into the ini_file
*
*    The other parameters are the same as those of ini_put().
*/
int ini_putf(struct ini_file *ini,
const char *sec,
const char *par,
const char *fmt,
...) {
char buffer[MAX_LINE];
va_list arg;

va_start(arg, fmt);

#ifdef _MSC_VER /* Microsoft Visual C++? */
/* VC++ messes around with _'s before vsnprintf(): */
#define    vsnprintf _vsnprintf
#endif

#if 1
vsnprintf(buffer, MAX_LINE, fmt, arg);
#else
vsprintf(buffer, fmt, arg );
assert(strlen(buffer) < MAX_LINE);
#endif
va_end(arg);

return ini_put(ini, sec, par, buffer);
}


ini.cpp
调用

static struct ini_file *gamedb = NULL;
BOOL CRobomoduleTestDlg::ResetConfig()
{
ini_put(gamedb, "System", "Half", "0");
ini_put(gamedb, "InitialPose", "X", "0.0");
ini_put(gamedb, "InitialPose", "Y", "0.0");
ini_put(gamedb, "InitialPose", "theta", "0.0");

ini_put(gamedb, "TilingUnit_Pose", "XTrans", "0.0");
ini_put(gamedb, "TilingUnit_Pose", "YTrans", "0.0");
ini_put(gamedb, "TilingUnit_Pose", "Height", "1.10");

ini_put(gamedb, "Laser_TilingUnitO", "RotateX", "0.0");
ini_put(gamedb, "Laser_TilingUnitO", "RotateY", "0.0");
ini_put(gamedb, "Laser_TilingUnitO", "RotateZ", "0.785398163");

ini_put(gamedb, "Laser_TilingUnitO", "TransformX", "0.165");
ini_put(gamedb, "Laser_TilingUnitO", "TransformY", "0.0");
ini_put(gamedb, "Laser_TilingUnitO", "TransformZ", "0.0");

ini_put(gamedb, "LaserO", "CalibRotateX", "-0.023289177");
ini_put(gamedb, "LaserO", "CalibRotateY", "0.0");
ini_put(gamedb, "LaserO", "CalibRotateZ", "-0.01573419");

ini_put(gamedb, "LaserO", "CalibTransformX", "0.0");
ini_put(gamedb, "LaserO", "CalibTransformY", "0.0");
ini_put(gamedb, "LaserO", "CalibTransformZ", "0.0");

char buffer[256];
_snprintf(buffer, sizeof buffer, "%s/%s", "D:", "config.ini");

int result = ini_write(gamedb,"config.ini");
ini_free(gamedb);

gamedb=NULL    ;
return TRUE;
}

BOOL CRobomoduleTestDlg::OnInitDialog()
{
CDialog::OnInitDialog();
ini_free(gamedb);
gamedb = ini_read(NULL, NULL, NULL);
int err, line;
ini_free(gamedb);
gamedb = ini_read("config.ini", &err, &line);
if(ini_get(gamedb,"InitialPose", "X", NULL) != NULL)
{
const char* a=ini_get(gamedb, "InitialPose", "X", NULL);
InitialPoseX= atof(a);
}
if(ini_get(gamedb,"InitialPose", "Y", NULL) != NULL)
{
const char* a=ini_get(gamedb, "InitialPose", "Y", NULL);
InitialPoseY= atof(a);
}
if(ini_get(gamedb,"InitialPose", "theta", NULL) != NULL)
{
const char* a=ini_get(gamedb, "InitialPose", "theta", NULL);
InitialPoseTheta= atof(a);
}
if(ini_get(gamedb,"TilingUnit_Pose", "XTrans", NULL) != NULL)
{
const char* a=ini_get(gamedb, "TilingUnit_Pose", "XTrans", NULL);
XTrans= atof(a);
}
if(ini_get(gamedb,"TilingUnit_Pose", "YTrans", NULL) != NULL)
{
const char* a=ini_get(gamedb, "TilingUnit_Pose", "YTrans", NULL);
YTrans= atof(a);
}
if(ini_get(gamedb,"TilingUnit_Pose", "Height", NULL) != NULL)
{
const char* a=ini_get(gamedb, "TilingUnit_Pose", "Height", NULL);
Height= atof(a);
}
if(ini_get(gamedb,"Laser_TilingUnitO", "RotateX", NULL) != NULL)
{
const char* b=ini_get(gamedb, "Laser_TilingUnitO", "RotateX", NULL);
RotateX= atof(b);
}
if(ini_get(gamedb,"Laser_TilingUnitO", "RotateY", NULL) != NULL)
{
const char* a=ini_get(gamedb, "Laser_TilingUnitO", "RotateY", NULL);
RotateY= atof(a);
}
if(ini_get(gamedb,"Laser_TilingUnitO", "RotateZ", NULL) != NULL)
{
const char* a=ini_get(gamedb, "Laser_TilingUnitO", "RotateZ", NULL);
RotateZ= atof(a);
}
if(ini_get(gamedb,"Laser_TilingUnitO", "TransformX", NULL) != NULL)
{
const char* a=ini_get(gamedb, "Laser_TilingUnitO", "TransformX", NULL);
TransformX= atof(a);
}
if(ini_get(gamedb,"Laser_TilingUnitO", "TransformY", NULL) != NULL)
{
const char* a=ini_get(gamedb, "Laser_TilingUnitO", "TransformY", NULL);
TransformY= atof(a);
}
if(ini_get(gamedb,"Laser_TilingUnitO", "TransformZ", NULL) != NULL)
{
const char* a=ini_get(gamedb, "Laser_TilingUnitO", "TransformZ", NULL);
TransformZ= atof(a);
}
if(ini_get(gamedb,"LaserO", "CalibRotateX", NULL) != NULL)
{
const char* a=ini_get(gamedb, "LaserO", "CalibRotateX", NULL);
CalibRotateX= atof(a);
}
if(ini_get(gamedb,"LaserO", "CalibRotateY", NULL) != NULL)
{
const char* a=ini_get(gamedb, "LaserO", "CalibRotateY", NULL);
CalibRotateY= atof(a);
}
if(ini_get(gamedb,"LaserO", "CalibRotateZ", NULL) != NULL)
{
const char* a=ini_get(gamedb, "LaserO", "CalibRotateZ", NULL);
CalibRotateZ= atof(a);
}
if(ini_get(gamedb,"LaserO", "CalibTransformX", NULL) != NULL)
{
const char* a=ini_get(gamedb, "LaserO", "CalibTransformX", NULL);
CalibTransformX= atof(a);
}
if(ini_get(gamedb,"LaserO", "CalibTransformY", NULL) != NULL)
{
const char* a=ini_get(gamedb, "LaserO", "CalibTransformY", NULL);
CalibTransformY= atof(a);
}
if(ini_get(gamedb,"LaserO", "CalibTransformZ", NULL) != NULL)
{
const char* a=ini_get(gamedb, "LaserO", "CalibTransformZ", NULL);
CalibTransformZ= atof(a);
}
if(ini_get(gamedb,"System", "Half", NULL) != NULL)
{
const char* a=ini_get(gamedb, "System", "Half", NULL);
useHalf= atof(a);
}


参考:https://github.com/wernsey/rengine/blob/master/src/ini.c
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: