00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
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
00247 Service *service = settings->findService(name);
00248
00249 if (service == NULL)
00250 {
00251
00252 ptr = new GenericVarService<T, ro, s>(name);
00253 settings->addService(ptr);
00254
00255
00256 std::fill(&ptr->v[0], &ptr->v[s], defaultValue);
00257
00258
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
00361 Service *service = settings->findService(name);
00362
00363 if (service == NULL)
00364 {
00365
00366 ptr = new GenericVarService<std::string, ro, 1>(name);
00367 settings->addService(ptr);
00368
00369
00370 ptr->v = defaultValue;
00371
00372
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
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
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
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
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
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