Fimbulwinter Project  Pre-Alpha
An Ragnarok Online Emulator
Common/config_file.hpp
00001 /*==================================================================*
00002 *     ___ _           _           _          _       _                          *
00003 *    / __(_)_ __ ___ | |__  _   _| |_      _(_)_ __ | |_ ___ _ __       *
00004 *   / _\ | | '_ ` _ \| '_ \| | | | \ \ /\ / / | '_ \| __/ _ \ '__|      *
00005 *  / /   | | | | | | | |_) | |_| | |\ V  V /| | | | | ||  __/ |         *
00006 *  \/    |_|_| |_| |_|_.__/ \__,_|_| \_/\_/ |_|_| |_|\__\___|_|         *
00007 *                                                                                                                                       *
00008 * ------------------------------------------------------------------*
00009 *                                                           Emulator                                    *
00010 * ------------------------------------------------------------------*
00011 *                        Licenced under GNU GPL v3                  *
00012 * ----------------------------------------------------------------- *
00013 *                      Configuration Files Modules                          *
00014 * ==================================================================*/
00015 
00016 #pragma once
00017 
00018 #include <string>
00019 #include <map>
00020 #include <iostream>
00021 #include <fstream>
00022 #include <sstream>
00023 
00024 using std::string;
00025 
00026 class config_file 
00027 {
00028 protected:
00029         string delimiter_;
00030         string comment_;
00031         string sentry_;
00032         std::map<string,string> contents_;
00033 
00034         typedef std::map<string,string>::iterator mapi;
00035         typedef std::map<string,string>::const_iterator mapci;
00036 
00037 public:
00038         config_file(string filename,
00039                 string delimiter = "=",
00040                 string comment = "#",
00041                 string sentry = "EndConfigFile");
00042         config_file();
00043 
00044         template<class T> T read(const string& key) const;
00045         template<class T> T read(const string& key, const T& value) const;
00046         template<class T> bool read_into(T& var, const string& key) const;
00047         template<class T>
00048         bool read_into(T& var, const string& key, const T& value) const;
00049 
00050         template<class T> void add(string key, const T& value);
00051         void remove(const string& key);
00052 
00053         bool key_exists(const string& key) const;
00054 
00055         string get_delimiter() const { return delimiter_; }
00056         string get_comment() const { return comment_; }
00057         string get_sentry() const { return sentry_; }
00058         string set_delimiter(const string& s)
00059         { string old = delimiter_;  delimiter_ = s;  return old; }  
00060         string set_comment(const string& s)
00061         { string old = comment_;  comment_ = s;  return old; }
00062 
00063         friend std::ostream& operator<<(std::ostream& os, const config_file& cf);
00064         friend std::istream& operator>>(std::istream& is, config_file& cf);
00065 
00066 protected:
00067         template<class T> static string T_as_string(const T& t);
00068         template<class T> static T string_as_T(const string& s);
00069 
00070 public:
00071         static void trim(string& s);
00072 
00073         struct file_not_found 
00074         {
00075                 string filename;
00076                 file_not_found(const string& filename_ = string())
00077                         : filename(filename_) {} 
00078         };
00079         struct key_not_found 
00080         {
00081                 string key;
00082                 key_not_found(const string& key_ = string())
00083                         : key(key_) {} 
00084         };
00085 };
00086 
00087 template<class T>
00088 string config_file::T_as_string(const T& t)
00089 {
00090         std::ostringstream ost;
00091         ost << t;
00092         return ost.str();
00093 }
00094 
00095 template<class T>
00096 T config_file::string_as_T(const string& s)
00097 {
00098         T t;
00099         std::istringstream ist(s);
00100         ist >> t;
00101         return t;
00102 }
00103 
00104 template<>
00105 inline string config_file::string_as_T<string>(const string& s)
00106 {
00107         return s;
00108 }
00109 
00110 template<>
00111 inline char *config_file::string_as_T<char*>(const string& s)
00112 {
00113         return (char*)s.c_str();
00114 }
00115 
00116 template<>
00117 inline bool config_file::string_as_T<bool>(const string& s)
00118 {
00119         bool b = true;
00120         string sup = s;
00121         for(string::iterator p = sup.begin(); p != sup.end(); ++p)
00122                 *p = toupper(*p);
00123         if(sup==string("FALSE") || sup==string("F") ||
00124                 sup==string("NO") || sup==string("N") ||
00125                 sup==string("0") || sup==string("NONE"))
00126                 b = false;
00127         return b;
00128 }
00129 
00130 
00131 template<class T>
00132 T config_file::read(const string& key) const
00133 {
00134         mapci p = contents_.find(key);
00135         if(p == contents_.end()) throw key_not_found(key);
00136         return string_as_T<T>(p->second);
00137 }
00138 
00139 
00140 template<class T>
00141 T config_file::read(const string& key, const T& value) const
00142 {
00143         mapci p = contents_.find(key);
00144         if(p == contents_.end()) return value;
00145         return string_as_T<T>(p->second);
00146 }
00147 
00148 
00149 template<class T>
00150 bool config_file::read_into(T& var, const string& key) const
00151 {
00152         mapci p = contents_.find(key);
00153         bool found = (p != contents_.end());
00154         if(found) var = string_as_T<T>(p->second);
00155         return found;
00156 }
00157 
00158 
00159 template<class T>
00160 bool config_file::read_into(T& var, const string& key, const T& value) const
00161 {
00162         mapci p = contents_.find(key);
00163         bool found = (p != contents_.end());
00164         if(found)
00165                 var = string_as_T<T>(p->second);
00166         else
00167                 var = value;
00168         return found;
00169 }
00170 
00171 
00172 template<class T>
00173 void config_file::add(string key, const T& value)
00174 {
00175         string v = T_as_string(value);
00176         trim(key);
00177         trim(v);
00178         contents_[key] = v;
00179         return;
00180 }
 All Classes Functions