⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 config.cpp

📁 仿游戏 Diablo 的源代码
💻 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 + -