| 
 
| 
|  | Simple Configuration Manager Submitted by
 |  
  
 This is what I have been writing during the past 2 evenings. It consists of one
class, CConfig. It also includes one little program I used to test it with. With
it, you can do the following:
 
Parse statements of type:int MipMaps = Config.GetInt( "r_mipmapping" );
or this:
Config.Parse( "r_mipmapping" );variable value
Obtain values in 3 formats: float, int and string.
Read Quake style .CFG files.
Read Windows .INI files (ignores sections, case-sensitive).
Parse CGI data (not tested).
Hidden feature: When only supplied a name, Parse() will return NO_VALUE and fill
the Config.Latest struct with values i.e. to get the int associated with
"r_mipmapping" you can do this:
 int MipMaps = Config.Latest.Int;
 
 Feel free to use this source in any way. Don't blame me if anything goes wrong.
Please post every comment and suggestion that comes to mind.
 |  
 
| Currently browsing [config.zip] (2,360 bytes) - [main.cpp] - (755 bytes) 
 
 | #include "config.h"
#include <iostream>
#include <cstring>
 #define SZ_FEATURE_NAME "CConfig"
 
 CConfig Config;
 
 int main() {
	char Str[64]; 
	int r;
	
	cout << "Welcome to the lab..." << endl;
	cout << "Testing feature: " << SZ_FEATURE_NAME << endl;
	cout << "Type Quit to exit." << endl << endl;
	
	while ( true ) {
		cout << "? ";
		for (int i = 0; i < 64; i++) { Str[i] = 0; }
		cin.getline( Str, 64 );
		if (strcmp( Str, "Quit" ) == 0) return 0;
		if ((r = Config.Parse( Str )) == CConfig::NO_VALUE) {
			cout << "String: " << Config.Latest.String << endl;
			cout << "Int:    " << Config.Latest.Int << endl;
			cout << "Float:  " << Config.Latest.Float << endl;
		}
		cout << "Returned: " << r << endl;
	}
	return -1;
}
 | 
 |  
 
| Currently browsing [config.zip] (2,360 bytes) - [config.h] - (983 bytes) 
 
 | #pragma once
 #pragma warning(disable: 4786)
#define SILENT_PARSER		// Comment this line in console app to see the inner workings of Parse()
#include <string>
#include <map>
using namespace std;
 
 struct CConfig {
	CConfig() {};
	~CConfig() {};
 
 enum ENUM_REPLIES {
		OK = 0,
		NO_NAME,
		NO_VALUE,
		NUM_REPLIES
	};
 
 // Parses a string
	ENUM_REPLIES Parse( char *psz );
	// Parses Quake style .CFG files
	void ParseCfg( char *File );
	// Parses Windows .INI files, ignores sections
	void ParseIni( char *File );
	// Parses CGI data from both GET and POST (not tested)
	void ParseCgi();
 
 inline string GetString( string &Name );
	inline int GetInt( string &Name );
	inline float GetFloat( string &Name );
 
 struct CVar {
		int Int;
		float Float;
		string String;
	} Latest;
 
 protected:
	typedef map<string, CVar> MYMAP;
	MYMAP Variables;
	map<string, CVar>::iterator Iterator;
	CVar Variable;
	bool GetVarByName( string &Name );
};
 | 
 |  
 
| Currently browsing [config.zip] (2,360 bytes) - [config.cpp] - (3,442 bytes) 
 
 | #include "config.h"
#include <cctype>
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <strstream>
 CConfig::ENUM_REPLIES CConfig::Parse( char *psz ) {
	char *p = psz;
	string Name("");
	Variable.String = "";
	
#ifndef SILENT_PARSER
	cout << "Parsing: " << psz << endl;
#endif
 
 // Eat leading spaces
	while (*p && isspace(*p)) p++;
	
	// Read name
	while (*p && !isspace(*p)) {
		Name += *p;
		p++;
	}
 
 // Eat whitespace
	while (*p && isspace(*p)) p++;
 
 // Read value
	while (*p) {
		Variable.String += *p;
		p++;
	}
 
 #ifndef SILENT_PARSER
	cout << "Name.size(): " << Name.size() << endl;
	cout << "Variable.String.size(): " << Variable.String.size() << endl;
#endif
 
 if (Name.size() == 0) return NO_NAME;
 
 // TODO: Optimize
	if (Variable.String.size() == 0) {
		Latest.Int = GetInt( Name );
		Latest.Float = GetFloat( Name );
		Latest.String = GetString( Name );
		return NO_VALUE;
	}
 
 Variable.Int = atoi( Variable.String.c_str() );
	Variable.Float = atof( Variable.String.c_str() );
 
 // Delete previous variable with same name
	if ((Iterator = Variables.find( Name )) != Variables.end()) Variables.erase(Iterator);
	// Insert new variable
	Variables.insert( MYMAP::value_type( Name, Variable ) );
 
 return OK;
}
 
 string CConfig::GetString( string &Name ) {
	if (GetVarByName( Name )) return Variable.String;
	return string("undefined");
}
 
 int CConfig::GetInt( string &Name ) {
	if (GetVarByName( Name )) return Variable.Int;
	return 0;
}
 
 float CConfig::GetFloat( string &Name ) {
	if (GetVarByName( Name )) return Variable.Float;
	return 0.0f;
}
 
 bool CConfig::GetVarByName( string &Name ) {
	Iterator = Variables.find( Name );
	if (Iterator == Variables.end()) return false;
	Variable = (*Iterator).second;
	return true;
}
 
 void CConfig::ParseCfg( char *File ) {
	ifstream istr(File);
	char Buffer[256];
 
 if (!istr.is_open()) {
		return;
	}
	while (!istr.eof()) {
		istr.getline( Buffer, 256 );
		if (Buffer[0] == '#') continue;
		if (Buffer[0] == 0x27) continue;
		Parse( Buffer );
	}
}
 
 // This function silently ignores sections!
void CConfig::ParseIni( char *File ) {
	ifstream istr(File);
	char Buffer[256];
	int i = 0;
 
 if (!istr.is_open()) {
		return;
	}
	while (!istr.eof()) {
		istr.getline( Buffer, 256 );
		if (Buffer[0] == ';') continue;
		if (Buffer[0] == '[') continue;
		while (Buffer[i]) {
			if (Buffer[i] == '=') Buffer[i] = ' ';
			i++;
		}
		Parse( Buffer );
	}
}
 
 void CConfig::ParseCgi() {
	char Buffer[4096], b[3]={0,0,0};
	int i = 0;
	string Method, Query;
	const string POST("POST"), GET("GET");
	istream *istr = NULL;
	
	// Environment variables involved:
	// REQUEST_METHOD, CONTENT_LENGTH, QUERY_STRING
	Method = getenv( "REQUEST_METHOD" );
	if ( Method == POST ) {
		istr = &cin;
	}
	if ( Method == GET ) {
		istrstream istrQuery( getenv( "QUERY_STRING" ) );
		istr = &istrQuery;
	}
 
 if (!istr) return;
 
 while ( !istr->eof() ) {
		istr->getline( Buffer, 4096, '&' );
		while ( Buffer[i] ) {
			if (Buffer[i] == '=') Buffer[i] = ' ';
			if (Buffer[i] == '+') Buffer[i] = ' ';
			if (Buffer[i] == '%') {
				// Hexadecimal encoding
				b[0] = Buffer[i+1];
				b[1] = Buffer[i+2];
				Buffer[i+1] = ' ';
				Buffer[i+2] = 0x08; // Should be backspace
				Buffer[i] = atoi( b );
			}
			i++;
		}
		Parse( Buffer );
	}
}
 
 
 | 
 |  The zip file viewer built into the Developer Toolbox made use
of the zlib library, as well as the zlibdll source additions.
 
 |