Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

settings.h

Go to the documentation of this file.
00001 /*
00002     Ishtar - A network transparent read/write interface with
00003     probing and enumeration support.
00004     settings part : settings file parsing and writing
00005     Copyright (C) 2003-2005 Stephane Magnenat <stephane at magnenat dot net>
00006 
00007     This program is free software; you can redistribute it and/or modify
00008     it under the terms of the GNU General Public License as published by
00009     the Free Software Foundation; either version 2 of the License, or
00010     (at your option) any later version.
00011 
00012     This program is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015     GNU General Public License for more details.
00016 
00017     You should have received a copy of the GNU General Public License
00018     along with this program; if not, write to the Free Software
00019     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020 */
00021 
00022 /*
00023     Settings
00024     
00025     Provides setting registrar that is itself an Ishtar server
00026 */
00027 
00028 #ifndef __ISHTAR_SETTINGS_H
00029 #define __ISHTAR_SETTINGS_H
00030 
00031 #include <ishtar/network.h>
00032 #include <ishtar/services.h>
00033 #include <sstream>
00034 #include <set>
00035 #include <string>
00036 #include <valarray>
00037 #include <iterator>
00038 
00075 
00076 namespace Ishtar
00077 {
00079     typedef std::vector<std::string> ParsedValues;
00081     typedef std::map<std::string, ParsedValues> ParserTable;
00082     
00084     class Settings: public ServicesServer
00085     {
00086     public:
00088         ParserTable parsedTable;
00089     
00090     public:
00092         Settings(UInt16 port);
00094         virtual ~Settings();
00095         
00097         void loadConfigFile(const std::string &name);
00099         void loadConfigString(const std::string &config);
00101         void dumpTable(void);
00103         void saveConfigFile(const std::string &name);
00104     };
00105     
00106     
00108     extern Settings *settings;
00109     
00111     void initSettings(int argc = 0, char *argv[] = NULL);
00112     
00114     void cleanupSettings(void);
00115     
00117     template<typename T, bool ro, Size s>
00118     class GenericVarService:public Service
00119     {
00120     private:
00122         unsigned refCount;
00123         
00124     public:
00126         T v[s];
00127         
00128     public:
00130         GenericVarService(const std::string &name)
00131         {
00132             description.name = name;
00133             description.type = TypeResolver<T>::type;
00134             description.flags = ro ? ServiceDescription::READ_ONLY : 0;
00135             description.length = s;
00136             refCount = 1;
00137         }
00138         
00140         virtual ValueVector *getValues(void)
00141         {
00142             ValueVectorTemplate<T> *vvt = new ValueVectorTemplate<T>(s);
00143             std::copy(&v[0], &v[s], vvt->value.begin());
00144             return vvt;
00145         }
00146         
00148         virtual void setValues(ValueVector *values)
00149         {
00150             ValueVectorTemplate<T> *vvt = dynamic_cast<ValueVectorTemplate<T> *>(values);
00151             assert(vvt->value.size() == s);
00152             if (vvt)
00153             {
00154                 std::copy(vvt->value.begin(), vvt->value.end(), &v[0]);
00155             }
00156             else
00157             {
00158                 const std::string &name = description.name;
00159                 std::cerr << "!!! Wrong type passed to " << name << "::setValues" << std::endl;
00160             }
00161         }
00162         
00164         void decCount() { refCount--; if (refCount==0) settings->eraseService(this); }
00166         void incCount() { refCount++; }
00167     };
00168     
00170     template<bool ro, Size s>
00171     class GenericVarService<std::string, ro, s>:public Service
00172     {
00173     private:
00175         unsigned refCount;
00176         
00177     public:
00179         std::string v;
00180         
00181     public:
00183         GenericVarService(const std::string &name)
00184         {
00185             description.name = name;
00186             description.type = ValueVector::UCHAR;
00187             description.flags = ro ? ServiceDescription::READ_ONLY : 0;
00188             description.length = 0;
00189             refCount = 1;
00190         }
00191         
00193         virtual ValueVector *getValues(void)
00194         {
00195             return new CharValueVector(v);
00196         }
00197         
00199         virtual void setValues(ValueVector *values)
00200         {
00201             CharValueVector *vvt = dynamic_cast<CharValueVector *>(values);
00202             if (vvt)
00203             {
00204                 v = *vvt;
00205             }
00206             else
00207             {
00208                 const std::string &name = description.name;
00209                 std::cerr << "!!! Wrong type passed to " << name << "::setValues" << std::endl;
00210             }
00211         }
00212         
00214         void decCount() { refCount--; if (refCount==0) settings->eraseService(this); }
00216         void incCount() { refCount++; }
00217     };
00218     
00220     template<typename T, bool ro = false, Size s = 1, bool warningWhenInitializedWithDefaultValue = true>
00221     class Variable
00222     {
00223     private:
00225         GenericVarService<T, ro, s> *ptr;
00226         
00227     public:
00229         Variable(const std::string &name, T defaultValue = T())
00230         {
00231             associate(name, defaultValue);
00232         }
00233         
00235         ~Variable()
00236         {
00237             assert(ptr);
00238             ptr->decCount();
00239         }
00240         
00242         void associate(const std::string &name, T defaultValue)
00243         {
00244             assert(settings);
00245             
00246             // Find service
00247             Service *service = settings->findService(name);
00248             
00249             if (service == NULL)
00250             {
00251                 // Service does not exists, create it
00252                 ptr = new GenericVarService<T, ro, s>(name);
00253                 settings->addService(ptr);
00254                 
00255                 // Set default value
00256                 std::fill(&ptr->v[0], &ptr->v[s], defaultValue);
00257                 
00258                 // Get initial value from settings
00259                 ParserTable::iterator i = settings->parsedTable.find(name);
00260                 if (i != settings->parsedTable.end())
00261                 {
00262                     if (s == i->second.size())
00263                     {
00264                         for (Size j=0; j<i->second.size(); j++)
00265                         {
00266                             std::istringstream iss(i->second[j]);
00267                             T tv;
00268                             iss >> tv;
00269                             ptr->v[j] = tv;
00270                         }
00271                     }
00272                     else
00273                     {
00274                         std::cerr << "!!! Config entry " << name << " has wrong number of parameter" << std::endl;
00275                     }
00276                 }
00277                 else if (warningWhenInitializedWithDefaultValue)
00278                 {
00279                     std::cout << "Ishtar::Variable::associate : service named " << name << " was initialized with default value (" << defaultValue << ")." << std::endl;
00280                 }
00281             }
00282             else
00283             {
00284                 ptr = dynamic_cast<GenericVarService<T, ro, s> *> (service);
00285                 if (ptr)
00286                 {
00287                     ptr->incCount();
00288                 }
00289                 else
00290                 {
00291                     std::cerr << "!!! Ishtar::Variable::associate : a service named " << name << " of another type already exists !" << std::endl;
00292                     assert(false);
00293                 }
00294             }
00295         }
00296         
00298         Variable(const Variable<T, ro, s>& v) { ptr = v.ptr; ptr->incCount(); }
00299         
00301         Variable& operator=(const Variable<T, ro, s>& v) { GenericVarService<T, ro, s> *oPtr = ptr; ptr = v.ptr; ptr->incCount(); oPtr->decCount(); return *this; }
00302         
00304         operator T&() const
00305         {
00306             assert(ptr);
00307             return ptr->v[0];
00308         }
00309         
00311         T& operator[](Size index) const
00312         {
00313             assert(ptr);
00314             assert(index < s);
00315             return ptr->v[index];
00316         }
00317         
00319         Variable & operator=(const T &val)
00320         {
00321             assert(ptr);
00322             ptr->v[0] = val;
00323             return *this;
00324         }
00325         
00327         Variable & operator=(const T val[s])
00328         {
00329             assert(ptr);
00330             memcpy(ptr->v, val, s * sizeof(T));
00331             return *this;
00332         }
00333     };
00334     
00336     template<bool ro, bool warningWhenInitializedWithDefaultValue>
00337     class Variable<std::string, ro, 1, warningWhenInitializedWithDefaultValue>
00338     {
00339     private:
00341         GenericVarService<std::string, ro, 1> *ptr;
00342         
00343     public:
00345         Variable(const std::string &name, const std::string &defaultValue = "")
00346         {
00347             associate(name, defaultValue);
00348         }
00349         
00351         ~Variable()
00352         {
00353             assert(ptr);
00354             ptr->decCount();
00355         }
00356         
00358         void associate(const std::string &name, const std::string &defaultValue)
00359         {
00360             // Find service
00361             Service *service = settings->findService(name);
00362             
00363             if (service == NULL)
00364             {
00365                 // Service does not exists, create it
00366                 ptr = new GenericVarService<std::string, ro, 1>(name);
00367                 settings->addService(ptr);
00368                 
00369                 // Set default value
00370                 ptr->v = defaultValue;
00371                 
00372                 // Get initial value from settings
00373                 ParserTable::iterator i = settings->parsedTable.find(name);
00374                 if (i != settings->parsedTable.end())
00375                 {
00376                     if (i->second.size() == 1)
00377                     {
00378                         ptr->v = i->second[0];
00379                     }
00380                     else
00381                     {
00382                         std::cerr << "!!! Config entry " << name << " should be of type string and thus have only one parameter" << std::endl;
00383                     }
00384                 }
00385                 else if (warningWhenInitializedWithDefaultValue)
00386                 {
00387                     std::cout << "Ishtar::Variable::associate : service named " << name << " was initialized with default value (" << defaultValue << ")." << std::endl;
00388                 }
00389             }
00390             else
00391             {
00392                 ptr = dynamic_cast<GenericVarService<std::string, ro, 1> *> (service);
00393                 if (ptr)
00394                 {
00395                     ptr->incCount();
00396                 }
00397                 else
00398                 {
00399                     std::cerr << "!!! Ishtar::Variable::associate : a service named " << name << " of another type already exists !" << std::endl;
00400                     assert(false);
00401                 }
00402             }
00403         }
00404         
00406         Variable(const Variable<std::string, ro, 1>& v) { ptr = v.ptr; ptr->incCount(); }
00407         
00409         Variable& operator=(const Variable<std::string, ro, 1>& v) { GenericVarService<std::string, ro, 1> *oPtr = ptr; ptr = v.ptr; ptr->incCount(); oPtr->decCount(); return *this; }
00410         
00412         operator std::string &() const
00413         {
00414             assert(ptr);
00415             return ptr->v;
00416         }
00417         
00419         operator const char *() const
00420         {
00421             assert(ptr);
00422             return ptr->v.c_str();
00423         }
00424         
00426         Variable & operator=(const std::string &s)
00427         {
00428             assert(ptr);
00429             ptr->v = s;
00430             return *this;
00431         }
00432         
00434         Variable & operator=(const char *s)
00435         {
00436             assert(ptr);
00437             ptr->v = s;
00438             return *this;
00439         }
00440     };
00441     
00443     template<typename T>
00444     class ValuesAccumulator : public std::vector<T>
00445     {
00446     public:
00448         ValuesAccumulator &operator +(const T &v) { push_back(v); return *this; }
00449     };
00450     
00452     typedef ValuesAccumulator<std::string> StringsAccumulator;
00453     
00455     template<typename T, bool ro = false, Size s = 1, bool warningWhenInitializedWithDefaultValue = false>
00456     class VarAccessService : public Service
00457     {
00458     protected:
00460         T *valuesPtr;
00461         
00462     public:
00464         VarAccessService()
00465         {
00466             valuesPtr = NULL;
00467         }
00468         
00470         void associate(const std::string &name, T *variables, const StringsAccumulator &subnames = StringsAccumulator())
00471         {
00472             description.name = name;
00473             description.type = TypeResolver<T>::type;
00474             description.flags = ro ? ServiceDescription::READ_ONLY : 0;
00475             description.length = s;
00476             
00477             // if each variable in the array is named
00478             if (subnames.size() != 0)
00479             {
00480                 description.flags |= ServiceDescription::NAMED_VALUES;
00481                 description.subnames.resize(subnames.size());
00482                 for (size_t i = 0; i < subnames.size(); i++)
00483                     description.subnames[i] = subnames[i];
00484             }
00485             
00486             valuesPtr = variables;
00487             
00488             // Get initial value from settings
00489             ParserTable::iterator i = settings->parsedTable.find(name);
00490             if (i != settings->parsedTable.end())
00491             {
00492                 if (s == i->second.size())
00493                 {
00494                     for (Size j=0; j<i->second.size(); j++)
00495                     {
00496                         std::istringstream iss(i->second[j]);
00497                         T tv;
00498                         iss >> tv;
00499                         valuesPtr[j] = tv;
00500                     }
00501                 }
00502                 else
00503                 {
00504                     std::cerr << "!!! Config entry " << name << " has wrong number of parameter" << std::endl;
00505                 }
00506             }
00507             else if (warningWhenInitializedWithDefaultValue)
00508             {
00509                 std::cout << "Ishtar::VarAccessService::associate : service named " << name << " was not initialized with config file." << std::endl;
00510             }
00511             
00512             settings->addService(this);
00513         }
00514         
00516         virtual ~VarAccessService()
00517         {
00518         }
00519         
00521         virtual ValueVector *getValues(void)
00522         {
00523             ValueVectorTemplate<T> *vvt = new ValueVectorTemplate<T>(s);
00524             std::copy(valuesPtr, valuesPtr+s, &vvt->value[0]);
00525             return vvt;
00526         }
00527         
00529         virtual void setValues(ValueVector *values)
00530         {
00531             ValueVectorTemplate<T> *vvt = dynamic_cast<ValueVectorTemplate<T> *>(values);
00532             assert(vvt->value.size() == s);
00533             if (vvt)
00534             {
00535                 std::copy(&vvt->value[0], &vvt->value[s], valuesPtr);
00536             }
00537             else
00538             {
00539                 const std::string &name = description.name;
00540                 std::cerr << "!!! Wrong type passed to " << name << "::setValues" << std::endl;
00541             }
00542         }
00543     };
00544     
00546     class VariablesPublisher
00547     {
00548     protected:
00550         std::vector<Service *> accessors;
00552         std::string root;
00553         
00554     public:
00556         VariablesPublisher(const std::string &root = "")
00557         {
00558             this->root = root;
00559         }
00560         
00562         virtual ~VariablesPublisher()
00563         {
00564             for (size_t i=0; i<accessors.size(); i++)
00565                 settings->eraseService(accessors[i]);
00566         }
00567         
00569         void setRoot(const std::string &root) { this->root = root; }
00570         
00572         template<typename T, bool ro, Size sz, bool warningWhenInitializedWithDefaultValue>
00573         void add(T *var, const std::string &name, const StringsAccumulator &subnames = StringsAccumulator())
00574         {
00575             VarAccessService<T, ro, sz, warningWhenInitializedWithDefaultValue> *s = new VarAccessService<T, ro, sz, warningWhenInitializedWithDefaultValue>();
00576             s->associate(root + name, var, subnames);
00577             accessors.push_back(s);
00578         }
00579         
00581         template<typename T, bool ro, Size sz>
00582         void add(T *var, const std::string &name, const StringsAccumulator &subnames = StringsAccumulator())
00583         {
00584             add<T, ro, sz, false>(var, name, subnames);
00585         }
00586         
00588         template<typename T, bool ro>
00589         void add(T *var, const std::string &name, const StringsAccumulator &subnames = StringsAccumulator())
00590         {
00591             add<T, ro, 1>(var, name, subnames);
00592         }
00593         
00595         template<typename T>
00596         void add(T *var, const std::string &name, const StringsAccumulator &subnames = StringsAccumulator())
00597         {
00598             add<T, false>(var, name, subnames);
00599         }
00600     };
00601     
00602     /*template<typename T, bool ro = false, Size s = 1>
00603     class FastVariable
00604     {
00605     protected:
00606         T var;
00607         FastVarService<T, ro, s> service;
00608         
00609     public:
00610         FastVariable(const std::string &name , const std::string &defaultValue = "")
00611         {
00612             service.associate(name, &var, NULL);
00613         }
00614     
00615         operator T&() { return var; }
00616         operator const T&() const { return var; }
00617     };*/
00618     
00620     class ArrayHelper
00621     {
00622     protected:
00624         std::string root;
00626         Variable<unsigned, true, 1> maxIndex;
00627         
00628     public:
00630         ArrayHelper(const std::string &root)
00631             :maxIndex(root + ".count", 0)
00632         {
00633             this->root = root;
00634         }
00635         
00637         std::string getNewRoot(void)
00638         {
00639             std::ostringstream oss;
00640             oss << root << "." << maxIndex;
00641             maxIndex = maxIndex + 1;
00642             // TODO : duplicate values from default value
00643             return oss.str();
00644         }
00645         
00647         unsigned getMaxIndex(void) { return maxIndex; }
00648         
00650         std::string getRoot(unsigned index)
00651         {
00652             std::ostringstream oss;
00653             oss << root << "." << index;
00654             return oss.str();
00655         }
00656         
00658         size_t getSettingsCount(void)
00659         {
00660             size_t i = 0;
00661             while (true)
00662             {
00663                 std::ostringstream oss;
00664                 oss << root << "." << i;
00665                 const std::string &rootToTest = oss.str();
00666                 bool found = false;
00667                 for (ParserTable::iterator it = settings->parsedTable.begin(); it != settings->parsedTable.end(); ++it)
00668                 {
00669                     if (it->first.compare(0, rootToTest.length(), rootToTest) == 0)
00670                         found = true;
00671                 }
00672                 if (!found)
00673                     break;
00674                 i++;
00675             }
00676             return i;
00677         }
00678     };
00679 }
00680 
00681 #endif

Generated on Mon Oct 24 17:31:47 2005 for libishtarsettings by  doxygen 1.4.2