📄 config.cpp
字号:
/* sample configuration file
;comment
[section name 1]
entryname = value
;comment
[section name 2]
entryname = value
*/
#include <ctype.h>
#include <io.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_CONFIG 4
#define MIN( a, b ) ( (a)>(b)) ? (b) : (a)
struct Entry{
struct Entry* next;
char *name;
char *value;
};
struct Section{
struct Section *next;
struct Entry *head;
char *name;
};
struct Config{
struct Section *head;
char *filename;
int dirty;
};
struct Config *config[MAX_CONFIG];
static int current;
int configInstalled = 0;
int InitConfig( void );
static void DestroyConfig( struct Config *cfg )
{
struct Section *sc, *prevs;
struct Entry *p, *prev;
int i;
if( cfg ){
if( cfg->filename && cfg->dirty ){
/* write to disk */
FILE *fp;
fp = fopen( cfg->filename, "wb" );
if( fp == NULL ) return;
sc = cfg->head;
while( sc ){
if( sc->name ){
fputs( sc->name, fp );
fputs( "\r\n", fp );
}
p = sc->head;
while( p ){
if( p->name ){
fputs( p->name, fp ); /* ';' is the header of commnet */
fputc( '=', fp );
}
if( p->value )
fputs( p->value, fp );
fprintf( fp, "\r\n" );
p = p->next;
}
sc = sc->next;
}
fclose( fp );
}
/* free memory */
sc = cfg->head;
while( sc ){
prevs = sc->next;
p = sc->head;
while( p ){
prev = p->next;
delete[] p->name ;
delete[] p->value ;
delete p ;
p = prev;
}
delete[] sc->name ;
delete sc ;
sc = prevs;
}
for( i=0; i<MAX_CONFIG; i++ )
if( config[i] == cfg )
config[i] = NULL;
delete cfg ;
}
}
static int GetLine( char *name, char *value, char *data, int length )
{
char buf[256], buf2[256];
int pos, i, j;
for( pos=0; (pos<length) && (pos<255); pos++ ){
if(( data[pos] == '\r' ) || ( data[pos] == '\n' )){
buf[pos] = 0;
if( pos < length-1 &&
(( data[pos] == '\r' && data[pos+1] == '\n' ) ||
( data[pos] == '\n' && data[pos+1] == '\r' ))){
pos ++;
}
pos++;
break;
}
buf[pos] = data[pos];
}
buf[MIN(pos, 255 )] = 0;
i = 0;
while( buf[i] && isspace( buf[i] ) )
i ++;
j = 0;
if( buf[i] != ';' )
while( buf[i] && buf[i] != '=' )//&& !isspace(buf[i])
buf2[j++] = buf[i++];
if( j ){
buf2[j] = 0;
j--;
while( j && isspace(buf2[j] ))
buf2[j--] = 0;
strcpy( name, buf2 );
while ((buf[i]) && ((isspace(buf[i])) || (buf[i] == '=')))
i++;
strcpy( value, buf+i );
/* free spaces */
i = strlen( value ) - 1;
while( i >= 0 && isspace( value[i] ))
value[ i-- ] = 0;
}
else{ /* the comment sentence is in value */
name[0] = 0;
strcpy( value, buf );
/* free spaces */
i = strlen( value ) - 1;
while( i >= 0 && isspace( value[i] ))
value[ i-- ] = 0;
}
return pos;
}
/* load config data into memory */
static void SetConfig( struct Config **config, char *data, int length, char *filename )
{
int pos = 0, len;
struct Section **prevs, *sp;
struct Entry **preve, *ep;
char *name, *value;
if( *config )
DestroyConfig( *config );
*config = NULL;
name = new char[ 256 ];
value = new char[ 256 ];
*config = new Config;
if( !*config || !name || !value ){
delete[] name ;
delete[] value ;
delete *config ;
return;
}
if( filename ){
(*config)->filename = new char[ strlen( filename ) + 1 ];
if( (*config)->filename )
strcpy( (*config)->filename, filename );
}
else
(*config)->filename = NULL;
(*config)->dirty = 0;
(*config)->head = NULL;
prevs = &(*config)->head;
while( pos < length ){
len = GetLine( name, value, data+pos, length-pos );
sp = new Section;
if( !sp )
goto error;
sp->name = NULL;
sp->next = NULL;
sp->head = NULL;
if( name[0] == '[' ){
sp->name = new char[ strlen(name) + 1 ];
if( sp->name)
strcpy( sp->name, name );
pos += len;
}
*prevs = sp;
prevs = &sp->next;
/* read entries */
preve = &(sp->head);
while( pos < length ){
len = GetLine( name, value, data+pos, length-pos );
if( name[0] == '[' )
break;
pos += len;
ep = new Entry;
if( !ep )
goto error;
ep->next = NULL;
ep->name = ep->value = NULL;
if( name[0] ){
ep->name = new char[ strlen(name) + 1 ];
if( ep->name )
strcpy( ep->name, name );
}
if( value[0] ){
ep->value = new char[ strlen(value)+1 ];
if( ep->value )
strcpy( ep->value, value );
}
*preve = ep;
preve = &ep->next;
}
}
error:
delete[] name ;
delete[] value ;
}
/* load config data from file */
static void LoadConfigFile( struct Config **cfg, char *filename, char *savefile )
{
int length;
FILE *fp;
if( *cfg ){
DestroyConfig( *cfg );
*cfg = NULL;
}
fp = fopen( filename, "rb" );
if( fp == NULL ){
// if the config file does not exist, then we create it
fp = fopen( filename, "wb");
if( fp == NULL)
return;
}
length = filelength( fileno( fp ));
if( length > 0 ){
char *temp = new char[ length ];
if( temp ){
fread( temp, 1, length, fp );
SetConfig( cfg, temp, length, savefile );
delete[] temp ;
}
else
SetConfig( cfg, NULL, 0, savefile );
}
else
SetConfig( cfg, NULL, 0, savefile );
fclose( fp );
}
/* find the specific section-entry in configuration file */
/* parameters:
secp: point to section, if found
prevsec: point to the section pointer, which points to the *secp
entp: point to entry, if found
preve: point to the entry pointer, which points to the *entp
*/
static void FindSectionEntry( struct Config *config, char *section, char *name,
struct Section **secp, struct Section ***prevsec,
struct Entry **entp, struct Entry ***preve )
{
struct Section *sp;
struct Entry *ep = NULL;
struct Section **prsec;
struct Entry **pre;
if( secp ) *secp = NULL;
if( prevsec ) *prevsec = NULL;
if( entp ) *entp = NULL;
if( preve ) *preve = NULL;
if( config == NULL ){
return ;
}
if( section ){
sp = config->head;
prsec = &config->head;
while( sp ){
if( strcmp( section, sp->name ) == 0 )
break;
prsec = &sp->next;
sp = sp->next;
}
if( sp ){
ep = sp->head;
if( prevsec ) *prevsec = prsec;
if( secp ) *secp = sp;
}
}
else
return;
if( name ){
pre = &( sp->head );
while( ep ){
if( strcmp( name, ep->name ) == 0 )
break;
pre = &ep->next;
ep = ep->next;
}
if( preve ) *preve = pre;
if( entp ) *entp = ep;
}
}
/* ensure that secion name is enclosed by '[ ]' braces */
static void NormalizeSectionName( char *in, char *out )
{
if( in == NULL ){
out[0] = 0;
return;
}
out[0] = 0;
if( in[0] != '[' ){
out[0] = '[';
out[1] = 0;
}
strcat( out, in );
if( in[ strlen(in) - 1 ] != ']' )
strcat( out, "]" );
}
// deft is the default value if the specific section-entry is not found
char* ConfigGetString( char *section, char *name, char *deft )
{
char sectionName[256];
struct Entry *ep;
NormalizeSectionName( section, sectionName );
FindSectionEntry( config[current], sectionName, name, NULL, NULL, &ep, NULL );
return ( ep ) ? ep->value : deft;
}
int ConfigGetInt( char *section, char *name, int deft )
{
char *s = ConfigGetString( section, name, NULL );
if( s && s[0] )
return strtol( s, NULL, 10 );
else
return deft;
}
float ConfigGetFloat( char *section, char *name, float deft )
{
char *s = ConfigGetString( section, name, NULL );
if( s && s[0] )
return ( float )strtod( s, NULL );
else
return deft;
}
void ConfigSetString( char *section, char *name, char *value )
{
struct Section *sp, **prevsec;
struct Entry *ep, *prevep, **preve;
char sectionName[256];
NormalizeSectionName( section ,sectionName );
FindSectionEntry( config[current], sectionName, name, &sp, &prevsec, &ep, &preve );
if( sp != NULL && name == NULL ){
/* if name is NULL, then we deal with section, not entry */
if( value ){
/* modify section name */
NormalizeSectionName( value, sectionName );
if( strlen( sp->name ) < strlen( sectionName )){
delete[] sp->name ;
sp->name = new char[ strlen(sectionName) + 1 ];
}
strcpy( sp->name, sectionName );
}
else{
/* free section */
*prevsec = sp->next;
ep = sp->head;
while( ep ){
delete[] ep->name ;
delete[] ep->value ;
prevep = ep->next;
delete ep ;
ep = prevep;
}
}
config[current]->dirty = 1;
return;
}
if( ep ){
/* we find the specific section-entry */
if( value ){
/* modify current value */
if( strlen( value ) > strlen( ep->value )){
delete[] ep->value ;
ep->value = new char[ strlen(value) + 1 ];
}
strcpy( ep->value, value );
}
else{
/* value is NULL, so we free the entry */
*preve = ep->next;
delete[] ep->name ;
delete[] ep->value ;
delete ep ;
}
config[current]->dirty = 1;
}
else{
/* the specific section or entry maybe not exist */
/* Append a NULL value? what's the meaning ! */
if( value == NULL ) return;
if( !sp ){
/* append section and entry */
sp = config[current]->head;
prevsec = &( config[current]->head );
while( sp ){
prevsec = &(sp->next);
sp = sp->next;
}
sp = new Section;
if( !sp ) return;
sp->head = NULL;
sp->next = NULL;
*prevsec = sp;
sp->name = new char[ strlen(sectionName)+1 ];
if( sp->name )
strcpy( sp->name, sectionName );
}
/* the section is found, append entry only */
ep = sp->head;
preve = &( sp->head );
while( ep ){
preve = &(ep->next);
ep = ep->next;
}
ep = new Entry;
if( !ep ) return;
*preve = ep;
ep->next = NULL;
ep->name = new char[ strlen(name)+1 ];
ep->value = new char[ strlen(value)+1 ];
if( ep->name == NULL || ep->value == NULL )
return;
strcpy( ep->name, name );
strcpy( ep->value, value );
config[current]->dirty = 1;
}
}
void ConfigSetInt( char *section, char *name, int value )
{
char string[18];
ConfigSetString( section, name, ( char* )itoa( value, string, 10 ));
}
void ConfigSetFloat( char *section, char *name, float value )
{
char string[33];
ConfigSetString( section, name, ( char* )gcvt( value, 32, string ));
}
int ConfigSetFile( char *filename )
{
if( !configInstalled )
if( InitConfig() != 0 ) return -1;
int i;
for( i=0; i<MAX_CONFIG; i++ ){
if( config[i] != NULL &&
strcmp( config[i]->filename, filename ) == 0 ){
/* already in memory */
current = i;
return 0;
}
}
for( i=0; i<MAX_CONFIG; i++ ){
if( config[i] == NULL ){
// find an empty slot
LoadConfigFile( &config[i], filename, filename );
return 0;
}
}
return -1;
}
int InitConfig( void )
{
int i;
if( configInstalled )
return 0;
for( i=0; i<MAX_CONFIG; i++ )
config[i] = NULL;
configInstalled = 1;
return 0;
}
void ConfigExit( void )
{
int i;
if( configInstalled )
for( i=0; i<MAX_CONFIG; i++ )
DestroyConfig( config[i] );
}
/*
void printConfig( struct Config* cfg )
{
struct Section *sp;
struct Entry *ep;
if( !cfg ) return;
sp = cfg->head;
while( sp ){
printf( "%s\n", sp->name );
ep = sp->head;
while( ep ){
printf( "%s = %s\n", ep->name, ep->value );
ep = ep->next;
}
sp = sp->next;
}
}*/
/*
void main ( void )
{
char *dma;
InitConfig();
ConfigSetFile( "sample.cfg" );
ConfigSetString( "video", "ram", "222" );
printConfig( config[0] );
ConfigExit();
}
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -