This section of the archives stores flipcode's complete Developer Toolbox collection, featuring a variety of mini-articles and source code contributions from our readers.

 

  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.

     

    Copyright 1999-2008 (C) FLIPCODE.COM and/or the original content author(s). All rights reserved.
    Please read our Terms, Conditions, and Privacy information.