|
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:
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.GetInt( "r_mipmapping" );
or this:
Config.Parse( "r_mipmapping" );
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.
|