ManaPlus
configuration.cpp
Go to the documentation of this file.
1 /*
2  * The ManaPlus Client
3  * Copyright (C) 2004-2009 The Mana World Development Team
4  * Copyright (C) 2009-2010 The Mana Developers
5  * Copyright (C) 2011-2017 The ManaPlus Developers
6  *
7  * This file is part of The ManaPlus Client.
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program. If not, see <http://www.gnu.org/licenses/>.
21  */
22 
23 #include "configuration.h"
24 
25 #include "variabledata.h"
26 
27 #include "fs/files.h"
28 #include "fs/paths.h"
29 
30 #include "fs/virtfs/fs.h"
31 
33 
34 #include "utils/cast.h"
35 #include "utils/checkutils.h"
36 #include "utils/foreach.h"
37 #ifdef DEBUG_CONFIG
38 #include "utils/stringmap.h"
39 #endif // DEBUG_CONFIG
40 
41 #include "debug.h"
42 
43 #ifdef DEBUG_CONFIG
44 StringIntMap optionsCount;
45 #define GETLOG() if (logger) {logger->log("config get: " + key); \
46  if (mIsMain) optionsCount[key] = 1; }
47 #else // DEBUG_CONFIG
48 #define GETLOG()
49 #endif // DEBUG_CONFIG
50 
51 Configuration config; // XML file configuration reader
52 Configuration serverConfig; // XML file server configuration reader
53 Configuration features; // XML file features
54 Configuration branding; // XML branding information reader
55 Configuration paths; // XML default paths information reader
56 
57 const std::string unusedKeys[] =
58 {
59  "BotCheckerWindowSticky",
60  "afkmessage",
61  "BotCheckerWindowVisible",
62  "BotCheckerWindowWinX",
63  "BotCheckerWindowWinY",
64  "hideShield",
65  "AttackRange",
66  "emoteshortcut0",
67  "screenshotDirectory2",
68  "AttackRangeBorder",
69  "AttackRangeBorderDelay",
70  "AttackRangeBorderGradient",
71  "AttackRangeDelay",
72  "AttackRangeGradient",
73  "Being",
74  "BeingDelay",
75  "BeingGradient",
76  "BeingPopupSkin",
77  "BotCheckerWindowSkin",
78  "BuySellSkin",
79  "BuySkin",
80  "ChatSkin",
81  "CollisionHighlight",
82  "CollisionHighlightDelay",
83  "CollisionHighlightGradient",
84  "ColorCross",
85  "ColorCrossDelay",
86  "ColorCrossGradient",
87  "ColorExperience",
88  "ColorExperienceGradient",
89  "ColorPickup",
90  "ColorPickupGradient",
91  "DebugSkin",
92  "DropShortcutSkin",
93  "EmoteShortcutSkin",
94  "EquipmentSkin",
95  "ExpInfo",
96  "ExpInfoDelay",
97  "ExpInfoGradient",
98  "Experience",
99  "ExperienceGradient",
100  "GM",
101  "GMDelay",
102  "GMGradient",
103  "Guild",
104  "GuildDelay",
105  "GuildGradient",
106  "GuildSkin",
107  "HelpSkin",
108  "Hit CriticalDelay",
109  "Hit CriticalGradient",
110  "Hit Monster Player",
111  "Hit Monster PlayerGradient",
112  "Hit Player Monster",
113  "Hit Player MonsterGradient",
114  "HitCriticalDelay",
115  "HitCriticalGradient",
116  "HitLocalPlayerCriticalDelay",
117  "HitLocalPlayerCriticalGradient",
118  "HitLocalPlayerMiss",
119  "HitLocalPlayerMissDelay",
120  "HitLocalPlayerMissGradient",
121  "HitLocalPlayerMonster",
122  "HitLocalPlayerMonsterDelay",
123  "HitLocalPlayerMonsterGradient",
124  "HitMonsterPlayer",
125  "HitMonsterPlayerDelay",
126  "HitMonsterPlayerGradient",
127  "HitPlayerMonster",
128  "HitPlayerMonsterDelay",
129  "HitPlayerMonsterGradient",
130  "HomePlace",
131  "HomePlaceBorder",
132  "HomePlaceBorderDelay",
133  "HomePlaceBorderGradient",
134  "HomePlaceDelay",
135  "HomePlaceGradient",
136  "InventorySkin",
137  "ItemPopupSkin",
138  "ItemShortcutSkin",
139  "Kill statsSkin",
140  "MiniStatusSkin",
141  "MinimapSkin",
142  "Miss",
143  "MissDelay",
144  "MissGradient",
145  "Monster",
146  "MonsterAttackRange",
147  "MonsterAttackRangeDelay",
148  "MonsterAttackRangeGradient",
149  "MonsterDelay",
150  "MonsterGradient",
151  "NPC",
152  "NPCDelay",
153  "NPCGradient",
154  "NpcTextSkin",
155  "OutfitsSkin",
156  "Particle",
157  "ParticleDelay",
158  "ParticleGradient",
159  "PartyDelay",
160  "PartyGradient",
161  "PartySkin",
162  "Personal ShopSkin",
163  "Pickup",
164  "PickupGradient",
165  "Player",
166  "PlayerDelay",
167  "PlayerGradient",
168  "PopupMenuSkin",
169  "PortalHighlight",
170  "PortalHighlightDelay",
171  "PortalHighlightGradient",
172  "RecorderSkin",
173  "RecorderWinX",
174  "RecorderWinY",
175  "RoadPoint",
176  "RoadPointDelay",
177  "RoadPointGradient",
178  "Self",
179  "SelfDelay",
180  "SelfGradient",
181  "SellSkin",
182  "ServerDialogSkin",
183  "ShopSkin",
184  "SkillsSkin",
185  "SocialCreatePopupSkin",
186  "SocialSkin",
187  "SpecialsSkin",
188  "SpeechSkin",
189  "SpellPopupSkin",
190  "SpellShortcutSkin",
191  "StatusPopupSkin",
192  "StatusSkin",
193  "StorageSkin",
194  "TextCommandEditorSkin",
195  "TextPopupSkin",
196  "TradeSkin",
197  "WhoIsOnlineSkin",
198  "emoteshortcut1",
199  "emoteshortcut2",
200  "emoteshortcut3",
201  "emoteshortcut4",
202  "emoteshortcut5",
203  "emoteshortcut6",
204  "emoteshortcut7",
205  "emoteshortcut8",
206  "emoteshortcut9",
207  "emoteshortcut10",
208  "emoteshortcut11",
209  "emoteshortcut12",
210  "emoteshortcut13",
211  "fastOpenGL",
212  "keyAutoCompleteChat",
213  "keyDeActivateChat",
214  "keyTargetClosest",
215  "keyWindowParty",
216  "mapalpha",
217  "port",
218  "shopBuyList",
219  "shopSellList",
220  "OutfitAwayIndex",
221  "playerHomes",
222  "remember",
223  "screenshotDirectory",
224  ""
225 };
226 
227 void ConfigurationObject::setValue(const std::string &key,
228  const std::string &value)
229 {
230  mOptions[key] = value;
231 }
232 
233 void ConfigurationObject::deleteKey(const std::string &key)
234 {
235  mOptions.erase(key);
236 }
237 
238 void Configuration::setValue(const std::string &key,
239  const std::string &value)
240 {
241  ConfigurationObject::setValue(key, value);
242  mUpdated = true;
243 
244  // Notify listeners
245  const ListenerMapIterator list = mListenerMap.find(key);
246  if (list != mListenerMap.end())
247  {
248  Listeners listeners = list->second;
249  FOR_EACH (ListenerIterator, i, listeners)
250  (*i)->optionChanged(key);
251  }
252 }
253 
254 void Configuration::incValue(const std::string &key)
255 {
256  GETLOG();
257  const Options::const_iterator iter = mOptions.find(key);
258  setValue(key, (iter != mOptions.end())
259  ? atoi(iter->second.c_str()) + 1 : 1);
260 }
261 
262 void Configuration::setSilent(const std::string &key,
263  const std::string &value)
264 {
265  ConfigurationObject::setValue(key, value);
266 }
267 
268 std::string ConfigurationObject::getValue(const std::string &key,
269  const std::string &deflt) const
270 {
271  GETLOG();
272  const Options::const_iterator iter = mOptions.find(key);
273  return ((iter != mOptions.end()) ? iter->second : deflt);
274 }
275 
276 int ConfigurationObject::getValue(const std::string &key,
277  const int deflt) const
278 {
279  GETLOG();
280  const Options::const_iterator iter = mOptions.find(key);
281  return (iter != mOptions.end()) ? atoi(iter->second.c_str()) : deflt;
282 }
283 
284 int ConfigurationObject::getValueInt(const std::string &key,
285  const int deflt) const
286 {
287  GETLOG();
288  const Options::const_iterator iter = mOptions.find(key);
289  return (iter != mOptions.end()) ? atoi(iter->second.c_str()) : deflt;
290 }
291 
292 bool ConfigurationObject::getValueBool(const std::string &key,
293  const bool deflt) const
294 {
295  GETLOG();
296  const Options::const_iterator iter = mOptions.find(key);
297  if (iter != mOptions.end())
298  return atoi(iter->second.c_str()) != 0 ? true : false;
299  return deflt;
300 }
301 
302 unsigned ConfigurationObject::getValue(const std::string &key,
303  const unsigned deflt) const
304 {
305  GETLOG();
306  const Options::const_iterator iter = mOptions.find(key);
307  return (iter != mOptions.end()) ? CAST_U32(
308  atol(iter->second.c_str())) : deflt;
309 }
310 
311 double ConfigurationObject::getValue(const std::string &key,
312  const double deflt) const
313 {
314  GETLOG();
315  const Options::const_iterator iter = mOptions.find(key);
316  return (iter != mOptions.end()) ? atof(iter->second.c_str()) : deflt;
317 }
318 
319 void ConfigurationObject::deleteList(const std::string &name)
320 {
321  for (ConfigurationList::const_iterator
322  it = mContainerOptions[name].begin();
323  it != mContainerOptions[name].end(); ++it)
324  {
325  delete *it;
326  }
327 
328  mContainerOptions[name].clear();
329 }
330 
332 {
333  for (std::map<std::string, ConfigurationList>::const_iterator
334  it = mContainerOptions.begin();
335  it != mContainerOptions.end(); ++it)
336  {
337  deleteList(it->first);
338  }
339  mOptions.clear();
340  mContainerOptions.clear();
341 }
342 
344  mOptions(),
345 #ifdef DEBUG_CONFIG
347  mLogKeys(false),
348  mIsMain(false)
349 #else // DEBUG_CONFIG
350 
352 #endif // DEBUG_CONFIG
353 {
354 }
355 
357 {
358  clear();
359 }
360 
363  mListenerMap(),
364  mConfigPath(),
365  mDefaultsData(),
366  mDirectory(),
367  mFilename(),
368  mUseResManager(UseVirtFs_false),
369  mUpdated(false)
370 {
371 #ifdef DEBUG_CONFIG
372  mLogKeys = false;
373  mIsMain = false;
374 #endif // DEBUG_CONFIG
375 }
376 
378 {
379  for (DefaultsData::const_iterator iter = mDefaultsData.begin();
380  iter != mDefaultsData.end();
381  ++iter)
382  {
383  delete iter->second;
384  }
385  mDefaultsData.clear();
386 }
387 
389 {
390  cleanDefaults();
391 }
392 
394 {
395  cleanDefaults();
396  mConfigPath.clear();
397  mDirectory.clear();
398  mFilename.clear();
401 }
402 
403 int Configuration::getIntValue(const std::string &key) const
404 {
405  GETLOG();
406  int defaultValue = 0;
407  const Options::const_iterator iter = mOptions.find(key);
408  if (iter == mOptions.end())
409  {
410  const DefaultsData::const_iterator itdef
411  = mDefaultsData.find(key);
412 
413  if (itdef != mDefaultsData.end() && (itdef->second != nullptr))
414  {
415  const VariableData *const data = itdef->second;
416  const VariableData::DataType type = static_cast<
418  if (type == VariableData::DATA_INT)
419  {
420  defaultValue = (static_cast<const IntData*>(
421  data))->getData();
422  }
423  else if (type == VariableData::DATA_STRING)
424  {
425  defaultValue = atoi((static_cast<const StringData*>(
426  data))->getData().c_str());
427  }
428  else if (type == VariableData::DATA_BOOL)
429  {
430  if ((static_cast<const BoolData*>(data))->getData())
431  defaultValue = 1;
432  else
433  defaultValue = 0;
434  }
435  else if (type == VariableData::DATA_FLOAT)
436  {
437  defaultValue = CAST_S32(
438  (static_cast<const FloatData*>(data))->getData());
439  }
440  }
441  else
442  {
443  reportAlways(
444  "%s: No integer value in registry for key %s",
445  mConfigPath.c_str(),
446  key.c_str());
447  }
448  }
449  else
450  {
451  defaultValue = atoi(iter->second.c_str());
452  }
453  return defaultValue;
454 }
455 
456 int Configuration::resetIntValue(const std::string &key)
457 {
458  GETLOG();
459  int defaultValue = 0;
460  const DefaultsData::const_iterator itdef = mDefaultsData.find(key);
461  if (itdef == mDefaultsData.end())
462  {
463  reportAlways("%s: No integer value in registry for key %s",
464  mConfigPath.c_str(),
465  key.c_str());
466  }
467  else
468  {
469  const VariableData *const data = itdef->second;
470  if (data != nullptr &&
471  data->getType() == VariableData::DATA_INT)
472  {
473  defaultValue = (static_cast<const IntData*>(
474  data))->getData();
475  }
476  else
477  {
478  reportAlways("%s: No integer value in registry for key %s",
479  mConfigPath.c_str(),
480  key.c_str());
481  }
482  }
483  setValue(key, defaultValue);
484  return defaultValue;
485 }
486 
487 std::string Configuration::getStringValue(const std::string &key) const
488 {
489  GETLOG();
490  std::string defaultValue;
491  const Options::const_iterator iter = mOptions.find(key);
492  if (iter == mOptions.end())
493  {
494  const DefaultsData::const_iterator
495  itdef = mDefaultsData.find(key);
496 
497  if (itdef != mDefaultsData.end() &&
498  (itdef->second != nullptr))
499  {
500  const VariableData *const data = itdef->second;
501  const VariableData::DataType type = static_cast<
503  if (type == VariableData::DATA_STRING)
504  {
505  defaultValue = (static_cast<const StringData*>(
506  data))->getData();
507  }
508  else if (type == VariableData::DATA_BOOL)
509  {
510  if ((static_cast<const BoolData*>(data))->getData())
511  defaultValue = "1";
512  else
513  defaultValue = "0";
514  }
515  else if (type == VariableData::DATA_INT)
516  {
517  defaultValue = toString((static_cast<const IntData*>(
518  data))->getData());
519  }
520  else if (type == VariableData::DATA_FLOAT)
521  {
522  defaultValue = toString((static_cast<const FloatData*>(
523  data))->getData());
524  }
525  }
526  else
527  {
528  reportAlways("%s: No string value in registry for key %s",
529  mConfigPath.c_str(),
530  key.c_str());
531  }
532  }
533  else
534  {
535  defaultValue = iter->second;
536  }
537  return defaultValue;
538 }
539 
540 
541 float Configuration::getFloatValue(const std::string &key) const
542 {
543  GETLOG();
544  float defaultValue = 0.0F;
545  const Options::const_iterator iter = mOptions.find(key);
546  if (iter == mOptions.end())
547  {
548  const DefaultsData::const_iterator itdef
549  = mDefaultsData.find(key);
550 
551  if (itdef != mDefaultsData.end() &&
552  (itdef->second != nullptr))
553  {
554  const VariableData *const data = itdef->second;
555  const VariableData::DataType type = static_cast<
557  if (type == VariableData::DATA_FLOAT)
558  {
559  defaultValue = static_cast<float>(
560  (static_cast<const FloatData*>(data))->getData());
561  }
562  else if (type == VariableData::DATA_STRING)
563  {
564  defaultValue = static_cast<float>(atof((
565  static_cast<const StringData*>(
566  data))->getData().c_str()));
567  }
568  else if (type == VariableData::DATA_BOOL)
569  {
570  if ((static_cast<const BoolData*>(data))->getData())
571  defaultValue = 1;
572  else
573  defaultValue = 0;
574  }
575  else if (type == VariableData::DATA_INT)
576  {
577  defaultValue = static_cast<float>((
578  static_cast<const IntData*>(
579  data))->getData());
580  }
581  }
582  else
583  {
584  reportAlways("%s: No float value in registry for key %s",
585  mConfigPath.c_str(),
586  key.c_str());
587  }
588  }
589  else
590  {
591  defaultValue = static_cast<float>(atof(iter->second.c_str()));
592  }
593  return defaultValue;
594 }
595 
596 bool Configuration::getBoolValue(const std::string &key) const
597 {
598  GETLOG();
599  bool defaultValue = false;
600  const Options::const_iterator iter = mOptions.find(key);
601  if (iter == mOptions.end())
602  {
603  const DefaultsData::const_iterator itdef
604  = mDefaultsData.find(key);
605 
606  if (itdef != mDefaultsData.end() &&
607  (itdef->second != nullptr))
608  {
609  const VariableData *const data = itdef->second;
610  const VariableData::DataType type = static_cast<
612  if (type == VariableData::DATA_BOOL)
613  {
614  defaultValue = (static_cast<const BoolData*>(
615  data))->getData();
616  }
617  else if (type == VariableData::DATA_INT)
618  {
619  if ((static_cast<const IntData*>(data))->getData() != 0)
620  defaultValue = true;
621  else
622  defaultValue = false;
623  }
624  else if (type == VariableData::DATA_STRING)
625  {
626  if ((static_cast<const StringData*>(
627  data))->getData() != "0")
628  {
629  defaultValue = true;
630  }
631  else
632  {
633  defaultValue = false;
634  }
635  }
636  if (type == VariableData::DATA_FLOAT)
637  {
638  if (CAST_S32((static_cast<const FloatData*>(
639  data))->getData()) != 0)
640  {
641  defaultValue = true;
642  }
643  else
644  {
645  defaultValue = false;
646  }
647  }
648  }
649  else
650  {
651  reportAlways(
652  "%s: No boolean value in registry for key %s",
653  mConfigPath.c_str(),
654  key.c_str());
655  }
656  }
657  else
658  {
659  defaultValue = getBoolFromString(iter->second);
660  }
661 
662  return defaultValue;
663 }
664 
665 bool Configuration::resetBoolValue(const std::string &key)
666 {
667  GETLOG();
668  bool defaultValue = false;
669  const DefaultsData::const_iterator itdef = mDefaultsData.find(key);
670 
671  if (itdef == mDefaultsData.end())
672  {
673  reportAlways("%s: No boolean value in registry for key %s",
674  mConfigPath.c_str(),
675  key.c_str());
676  }
677  else
678  {
679  const VariableData *const data = itdef->second;
680  if (data != nullptr &&
681  data->getType() == VariableData::DATA_BOOL)
682  {
683  defaultValue = (static_cast<const BoolData*>(data))->getData();
684  }
685  else
686  {
687  reportAlways("%s: No boolean value in registry for key %s",
688  mConfigPath.c_str(),
689  key.c_str());
690  }
691  }
692 
693  setValue(key, defaultValue);
694  return defaultValue;
695 }
696 
697 
698 void ConfigurationObject::initFromXML(XmlNodeConstPtrConst parentNode)
699 {
700  clear();
701 
702  if (parentNode == nullptr)
703  return;
704 
705  for_each_xml_child_node(node, parentNode)
706  {
707  if (xmlNameEqual(node, "list"))
708  {
709  // list option handling
710  const std::string name = XML::getProperty(node,
711  "name", std::string());
712 
713  for_each_xml_child_node(subnode, node)
714  {
715  if (xmlNameEqual(subnode, name.c_str()) &&
716  xmlTypeEqual(subnode, XML_ELEMENT_NODE))
717  {
718  ConfigurationObject *const cobj = new ConfigurationObject;
719  cobj->initFromXML(subnode); // recurse
720  mContainerOptions[name].push_back(cobj);
721  }
722  }
723  }
724  else if (xmlNameEqual(node, "option"))
725  {
726  // single option handling
727  const std::string name = XML::getProperty(node,
728  "name", std::string());
729  if (!name.empty())
730  {
731  mOptions[name] = XML::getProperty(node,
732  "value", std::string());
733  }
734  } // otherwise ignore
735  }
736 }
737 
738 void Configuration::init(const std::string &filename,
739  const UseVirtFs useResManager,
740  const SkipError skipError)
741 {
742  cleanDefaults();
743  clear();
744  mFilename = filename;
745  mUseResManager = useResManager;
746 
747  if (useResManager == UseVirtFs_true)
748  {
749  mConfigPath = "virtfs://" + filename;
750  mDirectory.clear();
751  if (VirtFs::exists(filename) == false)
752  {
753  logger->log("Warning: No configuration file (%s)",
754  filename.c_str());
755  return;
756  }
757  }
758  else
759  {
760  mConfigPath = filename;
761  logger->log1("init 1");
762  mDirectory = getRealPath(getFileDir(filename));
763  if (Files::existsLocal(filename) == false)
764  {
765  logger->log("Warning: No configuration file (%s)",
766  filename.c_str());
767  return;
768  }
769  }
770 
771  XML::Document doc(filename,
772  useResManager,
773  skipError);
774  logger->log1("init 2");
775  if (doc.rootNode() == nullptr)
776  {
777  logger->log("Couldn't open configuration file: %s", filename.c_str());
778  return;
779  }
780 
781  XmlNodeConstPtrConst rootNode = doc.rootNode();
782 
783  if ((rootNode == nullptr) || !xmlNameEqual(rootNode, "configuration"))
784  {
785  logger->log("Warning: No configuration file (%s)", filename.c_str());
786  return;
787  }
788 
789  initFromXML(rootNode);
790 }
791 
793 {
795  if (doc.rootNode() == nullptr)
796  {
797  logger->log("Couldn't open configuration file: %s", mFilename.c_str());
798  return;
799  }
800 
801  XmlNodeConstPtrConst rootNode = doc.rootNode();
802 
803  if ((rootNode == nullptr) || !xmlNameEqual(rootNode, "configuration"))
804  {
805  logger->log("Warning: No configuration file (%s)", mFilename.c_str());
806  return;
807  }
808 
809  initFromXML(rootNode);
810 }
811 
812 void ConfigurationObject::writeToXML(XmlTextWriterPtr writer)
813 {
814  FOR_EACH (Options::const_iterator, i, mOptions)
815  {
816 #ifdef DEBUG_CONFIG
817  if (mLogKeys)
818  {
819  if (optionsCount.find(i->first) == optionsCount.end())
820  logger->log("unused configuration option: " + i->first);
821  }
822 #endif // DEBUG_CONFIG
823 
824  XmlTextWriterStartElement(writer, "option");
825  XmlTextWriterWriteAttribute(writer, "name", i->first.c_str());
826  XmlTextWriterWriteAttribute(writer, "value", i->second.c_str());
827  XmlTextWriterEndElement(writer);
828  }
829 
830  for (std::map<std::string, ConfigurationList>::const_iterator
831  it = mContainerOptions.begin(), it_fend = mContainerOptions.end();
832  it != it_fend; ++ it)
833  {
834  const char *const name = it->first.c_str();
835 
836  XmlTextWriterStartElement(writer, "list");
837  XmlTextWriterWriteAttribute(writer, "name", name);
838 
839  // recurse on all elements
840  FOR_EACH (ConfigurationList::const_iterator, elt_it, it->second)
841  {
842  XmlTextWriterStartElement(writer, name);
843  if (*elt_it != nullptr)
844  (*elt_it)->writeToXML(writer);
845  XmlTextWriterEndElement(writer);
846  }
847 
848  XmlTextWriterEndElement(writer);
849  }
850 }
851 
853 {
854  if (mUpdated)
855  write();
856 }
857 
859 {
860  BLOCK_START("Configuration::write")
861  if (mConfigPath.empty())
862  {
863  BLOCK_END("Configuration::write")
864  return;
865  }
866 
867  mUpdated = false;
868  // Do not attempt to write to file that cannot be opened for writing
869  FILE *const testFile = fopen(mConfigPath.c_str(), "w");
870  if (testFile == nullptr)
871  {
872  reportAlways("Configuration::write() couldn't open %s for writing",
873  mConfigPath.c_str());
874  BLOCK_END("Configuration::write")
875  return;
876  }
877  fclose(testFile);
878 
879  XmlTextWriterPtr writer = XmlNewTextWriterFilename(
880  mConfigPath.c_str(), 0);
881 
882  if (writer == nullptr)
883  {
884  logger->log1("Configuration::write() error while creating writer");
885  BLOCK_END("Configuration::write")
886  return;
887  }
888 
889  logger->log1("Configuration::write() writing configuration...");
890 
891  XmlTextWriterSetIndent(writer, 1);
892  XmlTextWriterStartDocument(writer, nullptr, nullptr, nullptr);
893 // xmlTextWriterStartDocument(writer, nullptr, "utf8", nullptr);
894  XmlTextWriterStartRootElement(writer, "configuration");
895 
896  writeToXML(writer);
897 
898  XmlTextWriterEndDocument(writer);
899  XmlSaveTextWriterFilename(writer,
900  mConfigPath.c_str());
901  XmlFreeTextWriter(writer);
902  BLOCK_END("Configuration::write")
903 }
904 
905 void Configuration::addListener(const std::string &key,
906  ConfigListener *const listener)
907 {
908  mListenerMap[key].push_front(listener);
909 }
910 
911 void Configuration::removeListener(const std::string &key,
912  ConfigListener *const listener)
913 {
914  mListenerMap[key].remove(listener);
915 }
916 
917 #ifdef ENABLE_CHECKS
918 void Configuration::checkListeners(ConfigListener *const listener,
919  const char *const file,
920  const unsigned line)
921 {
923  {
924  Listeners listeners = it->second;
925  FOR_EACH (ListenerIterator, it2, listeners)
926  {
927  if (*it2 == listener)
928  {
929  logger->log("detected not cleaned listener: %p, %s:%u",
930  static_cast<void*>(listener), file, line);
931  exit(1);
932  }
933  }
934  }
935 }
936 #endif // ENABLE_CHECKS
937 
939 {
941  (it->second).remove(listener);
942 }
943 
945 {
946  if (mOptions.find(unusedKeys[0]) != mOptions.end() ||
947  mOptions.find(unusedKeys[1]) != mOptions.end() ||
948  mOptions.find(unusedKeys[2]) != mOptions.end())
949  {
950  int f = 0;
951  while (!unusedKeys[f].empty())
952  {
953  deleteKey(unusedKeys[f]);
954  logger->log("remove unused key: " + unusedKeys[f]);
955  f ++;
956  }
957  for (f = 0; f < 80; f ++)
958  {
959  const std::string str = toString(f);
960  deleteKey("Outfit" + str);
961  deleteKey("OutfitUnequip" + str);
962  deleteKey("commandShortcutCmd" + str);
963  deleteKey("commandShortcutFlags" + str);
964  deleteKey("commandShortcutSymbol" + str);
965  deleteKey("drop" + str);
966  deleteKey("shortcut" + str);
967  }
968  }
969 }
virtual int getType() const =0
#define CAST_U32
Definition: cast.h:30
Configuration branding
const bool UseVirtFs_false
Definition: usevirtfs.h:29
#define FOR_EACH(type, iter, array)
Definition: foreach.h:24
std::string getStringValue(const std::string &key) const
const bool SkipError_false
Definition: skiperror.h:29
void log1(const char *const log_text)
Definition: logger.cpp:222
std::map< std::string, int > StringIntMap
Definition: stringmap.h:27
virtual void initFromXML(const xmlNode *const parentNode)
int resetIntValue(const std::string &key)
std::string mDirectory
const std::string unusedKeys[]
#define BLOCK_START(name)
Definition: perfomance.h:78
Configuration config
int getProperty(const xmlNodePtr node, const char *const name, int def)
Definition: libxml.cpp:171
#define BLOCK_END(name)
Definition: perfomance.h:79
#define GETLOG()
int getIntValue(const std::string &key) const
float getFloatValue(const std::string &key) const
ListenerMap::iterator ListenerMapIterator
Configuration serverConfig
void addListener(const std::string &key, ConfigListener *const listener)
std::string mFilename
void setSilent(const std::string &key, const std::string &value)
ListenerMap mListenerMap
DefaultsData mDefaultsData
Defaults of value for a given key.
Logger * logger
Definition: logger.cpp:95
const bool UseVirtFs_true
Definition: usevirtfs.h:29
bool getBoolValue(const std::string &key) const
#define CAST_S32
Definition: cast.h:29
uint32_t data
bool getValueBool(const std::string &key, const bool deflt) const
virtual void setValue(const std::string &key, const std::string &value)
virtual void writeToXML(const xmlTextWriterPtr writer)
std::string empty
Definition: podict.cpp:25
xmlNodePtr rootNode()
Definition: libxml.cpp:166
std::list< ConfigListener * > Listeners
virtual ~ConfigurationObject()
Configuration paths
std::string toString(T const &value)
converts any type to a string
Definition: catch.hpp:1774
std::string getValue(const std::string &key, const std::string &deflt) const
void deleteList(const std::string &name)
#define for_each_xml_child_node(var, parent)
Definition: libxml.h:160
void removeListeners(ConfigListener *const listener)
bool exists(std::string name)
Definition: fs.cpp:123
bool getBoolFromString(const std::string &text)
std::string mConfigPath
Configuration features
Listeners::iterator ListenerIterator
UseVirtFs mUseResManager
void deleteKey(const std::string &key)
bool existsLocal(const std::string &path)
Definition: files.cpp:207
void init(const std::string &filename, const UseVirtFs useResManager=UseVirtFs_false, const SkipError skipError=SkipError_false)
void log(const char *const log_text,...)
Definition: logger.cpp:243
int getValueInt(const std::string &key, const int deflt) const
bool resetBoolValue(const std::string &key)
std::map< std::string, ConfigurationList > mContainerOptions
void incValue(const std::string &key)
#define reportAlways(...)
Definition: checkutils.h:252
void setValue(const std::string &key, const std::string &value)
std::string getRealPath(const std::string &str)
Definition: paths.cpp:76
std::string getFileDir(const std::string &path)
void removeListener(const std::string &key, ConfigListener *const listener)