From 86e5f80837ad55932f2469d79d9e6b6bb07cf5ed Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Mon, 28 Sep 2009 19:09:22 +0200 Subject: Implemented new ConfigManager --- src/Core/ConfigEntry.cpp | 94 +++++++++++++++++++++++++++++++++------------- src/Core/ConfigEntry.h | 75 ++++++++++++++++++------------------ src/Core/ConfigManager.cpp | 40 +++++++------------- src/Core/ConfigManager.h | 13 +++---- src/Core/Configurable.h | 4 +- src/Core/LogManager.cpp | 68 ++++++++++++++++----------------- src/Core/LogManager.h | 3 +- 7 files changed, 157 insertions(+), 140 deletions(-) (limited to 'src/Core') diff --git a/src/Core/ConfigEntry.cpp b/src/Core/ConfigEntry.cpp index 04ed08f..ec716b6 100644 --- a/src/Core/ConfigEntry.cpp +++ b/src/Core/ConfigEntry.cpp @@ -22,43 +22,85 @@ namespace Mad { namespace Core { -String& ConfigEntry::Entry::operator[] (std::size_t i) { - try { - return value.at(i); - } - catch(std::out_of_range &e) { - zero = String(); - return zero; - } +void ConfigEntry::addChild(const String &key, boost::shared_ptr entry) { + String lowerKey(key); + lowerKey.toLower(); + + EntryMap::iterator child = children.find(lowerKey); + + if(child == children.end()) + child = children.insert(std::make_pair(lowerKey, EntryVector())).first; + + child->second.push_back(entry); } -const String& ConfigEntry::Entry::operator[] (std::size_t i) const { - try { - return value.at(i); - } - catch(std::out_of_range &e) { - return constZero; +const ConfigEntry* ConfigEntry::getEntry(const String &key) const { + String childKey(key); + childKey.toLower(); + + int32_t dotIndex = key.indexOf('.'); + if(dotIndex >= 0) { + childKey.remove(dotIndex); } -} -ConfigEntry::Entry& ConfigEntry::operator[] (std::size_t i) { - try { - return entries.at(i); + EntryMap::const_iterator child = children.find(childKey); + if(child == children.end()) { + return 0; } - catch(std::out_of_range &e) { - zero = Entry(); - return zero; + else { + if(dotIndex >= 0) { + return child->second.back()->getEntry(key.substr(dotIndex+1)); + } + else { + return child->second.back().get(); + } } } -const ConfigEntry::Entry& ConfigEntry::operator[] (std::size_t i) const { - try { - return entries.at(i); +std::vector ConfigEntry::getEntries(const String &key) const { + String childKey(key); + childKey.toLower(); + + int32_t dotIndex = key.indexOf('.'); + if(dotIndex >= 0) { + childKey.remove(dotIndex); } - catch(std::out_of_range &e) { - return constZero; + + EntryMap::const_iterator child = children.find(childKey); + if(child == children.end()) { + return std::vector(); + } + else { + if(dotIndex >= 0) { + return child->second.back()->getEntries(key.substr(dotIndex+1)); + } + else { + std::vector ret; + + for(EntryVector::const_iterator entry = child->second.begin(); entry != child->second.end(); ++entry) { + ret.push_back(entry->get()); + } + + return ret; + } } } +std::vector ConfigEntry::getAll(const String &key) const { + const ConfigEntry *entry = getEntry(key); + if(!entry) + return std::vector(); + else + return entry->getValues(); +} + +String ConfigEntry::get(const String &key, const String &defaultValue) const { + const ConfigEntry *entry = getEntry(key); + if(!entry) + return defaultValue; + else + return entry->getValue(defaultValue); +} + } } diff --git a/src/Core/ConfigEntry.h b/src/Core/ConfigEntry.h index 26e77d2..1724267 100644 --- a/src/Core/ConfigEntry.h +++ b/src/Core/ConfigEntry.h @@ -23,63 +23,60 @@ #include "export.h" #include "String.h" - -#include +#include #include +#include namespace Mad { namespace Core { -class MAD_CORE_EXPORT ConfigEntry { - public: - class MAD_CORE_EXPORT Entry { - private: - String key; - std::vector value; - - String zero, constZero; +class ConfigManager; - public: - Entry() {} - Entry(const std::vector &args) { - if(args.empty()) - return; - - key = args.front(); +class MAD_CORE_EXPORT ConfigEntry { + private: + friend class ConfigManager; - value.assign(args.begin()+1, args.end()); - } + typedef std::vector > EntryVector; + typedef std::map EntryMap; - bool isEmpty() const { - return key.isEmpty(); - } + ConfigEntry *parent; - String &getKey() {return key;} - const String &getKey() const {return key;} + std::vector values; + EntryMap children; - std::size_t getSize() const {return value.size();} + protected: + ConfigEntry() : parent(0) {} - String& operator[] (std::size_t i); - const String& operator[] (std::size_t i) const; - }; + public: + ConfigEntry(ConfigEntry *parent0, const std::vector &values0) + : parent(parent0), values(values0) {} - private: - std::vector entries; - Entry zero, constZero; + void addChild(const String &key, boost::shared_ptr entry); - public: - std::size_t getSize() const {return entries.size();} + const ConfigEntry* getParent() const { + return parent; + } - Entry& operator[] (std::size_t i); - const Entry& operator[] (std::size_t i) const; + ConfigEntry* getParent() { + return parent; + } - void push(const Entry &entry) { - entries.push_back(entry); + const std::vector& getValues() const { + return values; } - void pop() { - entries.pop_back(); + String getValue(const String &defaultValue = String()) const { + if(values.empty()) + return defaultValue; + else + return values.front(); } + + const ConfigEntry* getEntry(const String &key) const; + std::vector getEntries(const String &key) const; + + std::vector getAll(const String &key) const; + String get(const String &key, const String &defaultValue = String()) const; }; } diff --git a/src/Core/ConfigManager.cpp b/src/Core/ConfigManager.cpp index fdbc93f..1cb4aa0 100644 --- a/src/Core/ConfigManager.cpp +++ b/src/Core/ConfigManager.cpp @@ -38,28 +38,16 @@ bool ConfigManager::Compare::operator() (const Configurable *c1, const Configura return c1 < c2; } - -void ConfigManager::handleConfigEntry(const ConfigEntry &entry) { - bool handled = false; - - for(std::set::iterator c = configurables.begin(); c != configurables.end(); ++c) { - if((*c)->handleConfigEntry(entry, handled)) - handled = true; - } - - if(!handled) - application->logf(Logger::LOG_WARNING, "Invalid config option '%s'.", entry[entry.getSize()-1].getKey().toLocale().c_str()); -} - bool ConfigManager::loadFile(const std::string &filename) { - if(finished) + if(configured) return false; std::ifstream file(filename.c_str()); - ConfigEntry entry; + ConfigEntry *currentEntry = this; + ConfigEntry *lastEntry = this; String line, input; UChar delim; - std::vector splitLine, lastConfigLine; + std::vector splitLine; if(!file.good()) return false; @@ -90,11 +78,9 @@ bool ConfigManager::loadFile(const std::string &filename) { } if(!splitLine.empty()) { - entry.push(splitLine); - handleConfigEntry(entry); - entry.pop(); - - lastConfigLine = splitLine; + boost::shared_ptr entry(new ConfigEntry(currentEntry, std::vector(splitLine.begin()+1, splitLine.end()))); + currentEntry->addChild(splitLine.front(), entry); + lastEntry = entry.get(); } switch(delim) { @@ -102,10 +88,10 @@ bool ConfigManager::loadFile(const std::string &filename) { input.remove(); break; case '{': - entry.push(lastConfigLine); + currentEntry = lastEntry; break; case '}': - entry.pop(); + lastEntry = currentEntry = currentEntry->getParent(); } line.remove(); @@ -116,14 +102,14 @@ bool ConfigManager::loadFile(const std::string &filename) { return true; } -void ConfigManager::finish() { - if(finished) +void ConfigManager::configure() { + if(configured) return; for(std::set::iterator c = configurables.begin(); c != configurables.end(); ++c) - (*c)->configFinished(); + (*c)->configure(); - finished = true; + configured = true; } } diff --git a/src/Core/ConfigManager.h b/src/Core/ConfigManager.h index 10b378d..2c11de9 100644 --- a/src/Core/ConfigManager.h +++ b/src/Core/ConfigManager.h @@ -22,6 +22,8 @@ #include "export.h" +#include "ConfigEntry.h" + #include #include #include @@ -30,10 +32,9 @@ namespace Mad { namespace Core { class Application; -class ConfigEntry; class Configurable; -class MAD_CORE_EXPORT ConfigManager { +class MAD_CORE_EXPORT ConfigManager : public ConfigEntry { private: struct MAD_CORE_EXPORT Compare { bool operator() (const Configurable *c1, const Configurable *c2); @@ -44,15 +45,13 @@ class MAD_CORE_EXPORT ConfigManager { Application *application; std::set configurables; - bool finished; - - ConfigManager(Application *application0) : application(application0), finished(false) {} + bool configured; - void handleConfigEntry(const ConfigEntry &entry); + ConfigManager(Application *application0) : application(application0), configured(false) {} public: bool loadFile(const std::string &filename); - void finish(); + void configure(); void registerConfigurable(Configurable *c) { configurables.insert(c); diff --git a/src/Core/Configurable.h b/src/Core/Configurable.h index c526379..1c41220 100644 --- a/src/Core/Configurable.h +++ b/src/Core/Configurable.h @@ -23,7 +23,6 @@ namespace Mad { namespace Core { -class ConfigEntry; class ConfigManager; class Configurable { @@ -37,8 +36,7 @@ class Configurable { Configurable() {} - virtual bool handleConfigEntry(const ConfigEntry& /*entry*/, bool /*handled*/) {return false;} - virtual void configFinished() {} + virtual void configure() = 0; }; } diff --git a/src/Core/LogManager.cpp b/src/Core/LogManager.cpp index 7282009..955ac76 100644 --- a/src/Core/LogManager.cpp +++ b/src/Core/LogManager.cpp @@ -53,17 +53,17 @@ LogManager::MessageLevel LogManager::parseLevel(const String &str) throw (Except if(str.isEmpty()) return Logger::LOG_DEFAULT; - if(str.caseCompare(DEBUG_LEVEL, 0) == 0) + if(str.matches(DEBUG_LEVEL)) return Logger::LOG_DEBUG; - else if(str.caseCompare(VERBOSE_LEVEL, 0) == 0) + else if(str.matches(VERBOSE_LEVEL)) return Logger::LOG_VERBOSE; - else if(str.caseCompare(DEFAULT_LEVEL, 0) == 0) + else if(str.matches(DEFAULT_LEVEL)) return Logger::LOG_DEFAULT; - else if(str.caseCompare(WARNING_LEVEL, 0) == 0) + else if(str.matches(WARNING_LEVEL)) return Logger::LOG_WARNING; - else if(str.caseCompare(ERROR_LEVEL, 0) == 0) + else if(str.matches(ERROR_LEVEL)) return Logger::LOG_ERROR; - else if(str.caseCompare(CRITICAL_LEVEL, 0) == 0) + else if(str.matches(CRITICAL_LEVEL)) return Logger::LOG_CRITICAL; else throw Exception(Exception::INVALID_INPUT); @@ -79,41 +79,37 @@ LogManager::~LogManager() { } -bool LogManager::handleConfigEntry(const ConfigEntry &entry, bool handled) { - if(entry[0].getKey().matches("Log")) { - if(entry[0][0].matches("Console")) { - if(entry[1].isEmpty()) { - registerLogger(consoleLogger); - return true; - } - else if(entry[1].getKey().matches("Level")) { - if(entry[2].isEmpty()) { - try { - if(entry[1][0].matches("remote")) - consoleLogger->setRemoteLevel(parseLevel(entry[1][1])); - else - consoleLogger->setLevel(parseLevel(entry[1][0])); - } - catch(Core::Exception e) { - application->logf(Logger::LOG_WARNING, "Unknown log level '%s'.", entry[1][0].toLocale().c_str()); - } - - return true; - } - } +void LogManager::configure() { + std::vector entries = application->getConfigManager()->getEntries("Log"); + + for(std::vector::iterator entry = entries.begin(); entry != entries.end(); ++entry) { + const std::vector &values = (*entry)->getValues(); + + if(values.empty() || !values.front().matches("Console")) + continue; + + registerLogger(consoleLogger); + + bool remote = false; + for(std::vector::const_iterator value = values.begin()+1; value != values.end(); ++value) { + if(value->matches("remote")) + remote = true; } - else if(entry[1].isEmpty()) { - if(!handled) { - application->logf(Logger::LOG_WARNING, "Unknown logger '%s'.", entry[0][0].toLocale().c_str()); - return true; + + String level = (*entry)->get("Level"); + if(!level.isEmpty()) { + try { + if(remote) + consoleLogger->setRemoteLevel(parseLevel(level)); + else + consoleLogger->setLevel(parseLevel(level)); + } + catch(Core::Exception e) { + application->logf(Logger::LOG_WARNING, "Unknown log level '%s'.", level.toLocale().c_str()); } } } - return false; -} - -void LogManager::configFinished() { if(loggers.empty()) registerLogger(consoleLogger); diff --git a/src/Core/LogManager.h b/src/Core/LogManager.h index a1f3d7d..5de38a9 100644 --- a/src/Core/LogManager.h +++ b/src/Core/LogManager.h @@ -96,8 +96,7 @@ class MAD_CORE_EXPORT LogManager : public Configurable { ~LogManager(); protected: - virtual bool handleConfigEntry(const ConfigEntry &entry, bool handled); - virtual void configFinished(); + virtual void configure(); public: static MessageLevel parseLevel(const String &str) throw (Exception); -- cgit v1.2.3