Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

config.H

Go to the documentation of this file.
00001 #ifndef _config_H_
00002 #define _config_H_
00003 #include <std/strings.H>
00004 #include <std/config.H>
00005 #include "std/strstream.H" // localize strstream.h weirdness
00006 
00007 /* This module defines a global configuration manager that reads in (a) config 
00008    file(s) and makes it available to user code, either through method calls or 
00009    by registering variables to take the data. This should also handle
00010    automatically getting different configuration files for different
00011    environments of one sort or another, but it doesn't yet. In general you
00012    should use this by using the CONFIGmap class which establishes and
00013    disestablishes mappings between config lines and variables (which currently 
00014    doesn't do anything more than initial setup but may in the future). */
00015 
00016 class CONFIGmapbase {
00017    public:
00018       virtual ~CONFIGmapbase() {}
00019       virtual void remap(Cstr_ptr &newval) = 0;
00020 };
00021 
00022 class DllImpExp CONFIG {
00023  private:
00024           HASH<str_ptr> _entries;
00025    static CONFIG  *_config;
00026 
00027  public:
00028           void     read_file(istream &cfgfile);
00029 
00030                    CONFIG();
00031           void     add_config_line(Cstr_ptr &line);
00032           str_ptr *register_map  (Cstr_ptr &name, CONFIGmapbase *);
00033           void     unregister_map(Cstr_ptr &,     CONFIGmapbase *) {}
00034    static CONFIG  *mainconfig()       { if (!_config) _config = new CONFIG;
00035                                         return _config; }
00036    static void     init(int &argc, char **argv);
00037   
00038    // will call read_file for any argument that contains the string
00039    // "glueconfig" in it.
00040    static void     init_with_filenames(int &argc, char **argv);
00041 };
00042 
00043 template <class T>
00044 static inline
00045 bool
00046 decode_it(Cstr_ptr &str, T &v) {
00047    istrstream istr(**str);
00048    istr >> v;
00049    return !istr ? false : true;
00050 }
00051 
00052 static inline bool decode_it(Cstr_ptr &str, str_ptr &v) {v = str; return true;}
00053 extern DllImpExp void CONFIGmissing(Cstr_ptr &);
00054 
00055 #ifdef GLUEBASE_VER
00056 extern DllImpExp void CONFIGnotread(Cstr_ptr &);
00057 #endif
00058 
00059 template <class V>
00060 class CONFIGmap : public CONFIGmapbase {
00061    Cstr_ptr  n_;
00062    V        &v_;
00063  public:
00064    CONFIGmap(Cstr_ptr &name, V &variable, bool warn=true):n_(name),v_(variable)
00065    {
00066      str_ptr *ret = CONFIG::mainconfig()->register_map(n_, this);
00067      if (ret) {
00068        remap(*ret);  
00069      } else if (warn)
00070        CONFIGmissing(n_);
00071    }
00072   
00073    virtual ~CONFIGmap() { CONFIG::mainconfig()->unregister_map(n_, this); };
00074    virtual void remap(Cstr_ptr &myval) {
00075       if (!decode_it(myval, v_)) {
00076          cerr << "Garbled config file entry \"" << myval << "\" for  tag \""
00077               << n_ << "\".\n";
00078       }
00079    }
00080 };
00081 
00082 template <class V>
00083 class CONFIGget : public CONFIGmapbase {
00084   V        v_;
00085   Cstr_ptr n_;
00086 public:
00087   CONFIGget(Cstr_ptr &n, const V &dflt, bool warn=true)
00088     : v_(dflt), n_(n)
00089   { 
00090     str_ptr *ret = CONFIG::mainconfig()->register_map(n, this);
00091     if (ret) {
00092       remap(*ret);
00093     } else if (warn)
00094       CONFIGmissing(n);
00095   }
00096   
00097   virtual     ~CONFIGget()  { CONFIG::mainconfig()->unregister_map(n_, this); };
00098   
00099   V            operator *()           { return v_; }
00100   virtual void remap(Cstr_ptr &myval) {
00101     if (!decode_it(myval, v_)) {
00102       cerr << "Garbled config file entry \"" << myval
00103        << "\" for  tag \"" << n_ << "\".\n";
00104     }
00105   }
00106 };
00107 
00108 //
00109 // bcz: here's the deal.  We want to be able to just load in a CONFIG 
00110 //      variable by inferring the variable type from the default 
00111 //      parameter passed to CONFIGval.  However, in the case of strings,
00112 //      the default may be passed in as a quoted string.  The problem
00113 //      with this is that the type will not be promoted to str_ptr,
00114 //      and we'll try overwriting the static string which is bad.
00115 //      So, we have to define exceptions to the template that will
00116 //      catch the quoted_string stuff and do the promotion.  Once again,
00117 //      a problem arises because different compilers have different
00118 //      type descriptions for a quoted string.
00119 //
00120 // Compilers that think a quoted string is a const char *:
00121 //    SUNWspro 5.0 and later
00122 //    g++ 2.96 and later
00123 //
00124 #if (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x500) || \
00125     (defined(__GNUC__) && (__GNUC__ > 2 || \
00126                          (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)))
00127 #define QUOTED_STRING const char *
00128 #else
00129 #define QUOTED_STRING char *
00130 #endif
00131 inline str_ptr CONFIGval(QUOTED_STRING n, QUOTED_STRING dflt="", bool warn=true)
00132    { return *CONFIGget<str_ptr>(n,str_ptr(dflt),warn); }
00133 #if defined(WIN32) || (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x500)
00134    // VC++ can't seem to promote both variables
00135 inline str_ptr CONFIGval(str_ptr &n, QUOTED_STRING dflt="", bool warn=true) 
00136    { return *CONFIGget<str_ptr>(n,str_ptr(dflt),warn); }
00137 #endif
00138 inline str_ptr CONFIGval(Cstr_ptr &n, QUOTED_STRING dflt="", bool warn=true) 
00139    { return *CONFIGget<str_ptr>(n,str_ptr(dflt),warn); }
00140 
00141 // XXX AIX xlC does not allow default parameters in template functions
00142 #ifdef _AIX
00143 template <class S, class V>
00144 V CONFIGval(S n, const V &dflt) 
00145    { return *CONFIGget<V>(n,dflt,true); }
00146 template <class S, class V>
00147 V CONFIGval(S n, const V &dflt, bool warn) 
00148    { return *CONFIGget<V>(n,dflt,warn); }
00149 #else
00150 template <class S, class V>
00151 V CONFIGval(S n, const V &dflt, bool warn=true) 
00152    { return *CONFIGget<V>(n,dflt,warn); }
00153 #endif
00154 
00155 inline str_ptr 
00156 CONFIGrecurse(Cstr_ptr &n, Cstr_ptr &dflt, bool warn=true)
00157 {
00158    str_ptr maps_to;
00159    if ((maps_to = CONFIGval(n, dflt, warn)) != dflt)
00160       return CONFIGrecurse(maps_to, maps_to, false);
00161    else
00162       return maps_to;
00163 }
00164 
00165 
00166 /* This function and macro are for use only for global variables, not for
00167    function-local or member variables. */
00168 template <class V>
00169 inline V &
00170 CONFIGmapper(Cstr_ptr &name, V &var, const V &dflt)
00171 {
00172    var = dflt;
00173    new CONFIGmap<V>(name, var);
00174    return var;
00175 }
00176 
00177 #define CONFIG_DECLARE(VAR,DEFAULT) VAR = CONFIGmapper(str_ptr(#VAR), VAR, DEFAULT)
00178 
00179 #endif

Generated on Mon Sep 15 16:25:56 2003 for gluebase by doxygen1.2.18