diff options
Diffstat (limited to 'lib/common/Configuration.cpp')
-rw-r--r-- | lib/common/Configuration.cpp | 335 |
1 files changed, 234 insertions, 101 deletions
diff --git a/lib/common/Configuration.cpp b/lib/common/Configuration.cpp index 4d76e0e0..7d2e0bac 100644 --- a/lib/common/Configuration.cpp +++ b/lib/common/Configuration.cpp @@ -9,8 +9,11 @@ #include "Box.h" -#include <stdlib.h> #include <limits.h> +#include <stdlib.h> +#include <string.h> + +#include <sstream> #include "Configuration.h" #include "CommonException.h" @@ -29,7 +32,105 @@ inline bool iw(int c) static const char *sValueBooleanStrings[] = {"yes", "true", "no", "false", 0}; static const bool sValueBooleanValue[] = {true, true, false, false}; +ConfigurationVerifyKey::ConfigurationVerifyKey +( + std::string name, + int flags, + void *testFunction +) +: mName(name), + mHasDefaultValue(false), + mFlags(flags), + mTestFunction(testFunction) +{ } + +// to allow passing NULL for default ListenAddresses + +ConfigurationVerifyKey::ConfigurationVerifyKey +( + std::string name, + int flags, + NoDefaultValue_t t, + void *testFunction +) +: mName(name), + mHasDefaultValue(false), + mFlags(flags), + mTestFunction(testFunction) +{ } + +ConfigurationVerifyKey::ConfigurationVerifyKey +( + std::string name, + int flags, + std::string defaultValue, + void *testFunction +) +: mName(name), + mDefaultValue(defaultValue), + mHasDefaultValue(true), + mFlags(flags), + mTestFunction(testFunction) +{ } + +ConfigurationVerifyKey::ConfigurationVerifyKey +( + std::string name, + int flags, + const char *defaultValue, + void *testFunction +) +: mName(name), + mDefaultValue(defaultValue), + mHasDefaultValue(true), + mFlags(flags), + mTestFunction(testFunction) +{ } + +ConfigurationVerifyKey::ConfigurationVerifyKey +( + std::string name, + int flags, + int defaultValue, + void *testFunction +) +: mName(name), + mHasDefaultValue(true), + mFlags(flags), + mTestFunction(testFunction) +{ + ASSERT(flags & ConfigTest_IsInt); + std::ostringstream val; + val << defaultValue; + mDefaultValue = val.str(); +} +ConfigurationVerifyKey::ConfigurationVerifyKey +( + std::string name, + int flags, + bool defaultValue, + void *testFunction +) +: mName(name), + mHasDefaultValue(true), + mFlags(flags), + mTestFunction(testFunction) +{ + ASSERT(flags & ConfigTest_IsBool); + mDefaultValue = defaultValue ? "yes" : "no"; +} + +ConfigurationVerifyKey::ConfigurationVerifyKey +( + const ConfigurationVerifyKey& rToCopy +) +: mName(rToCopy.mName), + mDefaultValue(rToCopy.mDefaultValue), + mHasDefaultValue(rToCopy.mHasDefaultValue), + mFlags(rToCopy.mFlags), + mTestFunction(rToCopy.mTestFunction) +{ } // -------------------------------------------------------------------------- // @@ -55,8 +156,8 @@ Configuration::Configuration(const std::string &rName) // -------------------------------------------------------------------------- Configuration::Configuration(const Configuration &rToCopy) : mName(rToCopy.mName), - mSubConfigurations(rToCopy.mSubConfigurations), - mKeys(rToCopy.mKeys) + mKeys(rToCopy.mKeys), + mSubConfigurations(rToCopy.mSubConfigurations) { } @@ -98,32 +199,29 @@ std::auto_ptr<Configuration> Configuration::LoadAndVerify( FdGetLine getline(file); // Object to create - Configuration *pconfig = new Configuration(std::string("<root>")); + std::auto_ptr<Configuration> apConfig( + new Configuration(std::string("<root>"))); try { // Load - LoadInto(*pconfig, getline, rErrorMsg, true); + LoadInto(*apConfig, getline, rErrorMsg, true); if(!rErrorMsg.empty()) { // An error occured, return now - //TRACE1("Error message from LoadInto: %s", rErrorMsg.c_str()); - TRACE0("Error at Configuration::LoadInfo\n"); - delete pconfig; - pconfig = 0; + BOX_ERROR("Error in Configuration::LoadInto: " << + rErrorMsg); return std::auto_ptr<Configuration>(0); } // Verify? if(pVerify) { - if(!Verify(*pconfig, *pVerify, std::string(), rErrorMsg)) + if(!apConfig->Verify(*pVerify, std::string(), rErrorMsg)) { - //TRACE1("Error message from Verify: %s", rErrorMsg.c_str()); - TRACE0("Error at Configuration::Verify\n"); - delete pconfig; - pconfig = 0; + BOX_ERROR("Error verifying configuration: " << + rErrorMsg); return std::auto_ptr<Configuration>(0); } } @@ -131,13 +229,11 @@ std::auto_ptr<Configuration> Configuration::LoadAndVerify( catch(...) { // Clean up - delete pconfig; - pconfig = 0; throw; } // Success. Return result. - return std::auto_ptr<Configuration>(pconfig); + return apConfig; } @@ -173,10 +269,10 @@ bool Configuration::LoadInto(Configuration &rConfig, FdGetLine &rGetLine, std::s if(startBlockExpected) { // New config object - Configuration config(blockName); + Configuration subConfig(blockName); // Continue processing into this block - if(!LoadInto(config, rGetLine, rErrorMsg, false)) + if(!LoadInto(subConfig, rGetLine, rErrorMsg, false)) { // Abort error return false; @@ -185,11 +281,12 @@ bool Configuration::LoadInto(Configuration &rConfig, FdGetLine &rGetLine, std::s startBlockExpected = false; // Store... - rConfig.mSubConfigurations.push_back(std::pair<std::string, Configuration>(blockName, config)); + rConfig.AddSubConfig(blockName, subConfig); } else { - rErrorMsg += "Unexpected start block in " + rConfig.mName + "\n"; + rErrorMsg += "Unexpected start block in " + + rConfig.mName + "\n"; } } else @@ -200,7 +297,7 @@ bool Configuration::LoadInto(Configuration &rConfig, FdGetLine &rGetLine, std::s if(RootLevel) { // error -- root level doesn't have a close - rErrorMsg += "Root level has close block -- forget to terminate subblock?\n"; + rErrorMsg += "Root level has close block -- forgot to terminate subblock?\n"; // but otherwise ignore } else @@ -246,24 +343,11 @@ bool Configuration::LoadInto(Configuration &rConfig, FdGetLine &rGetLine, std::s { std::string key(line.substr(0, keyend)); std::string value(line.substr(valuestart)); - //TRACE2("KEY: |%s|=|%s|\n", key.c_str(), value.c_str()); - - // Check for duplicate values - if(rConfig.mKeys.find(key) != rConfig.mKeys.end()) - { - // Multi-values allowed here, but checked later on - rConfig.mKeys[key] += MultiValueSeparator; - rConfig.mKeys[key] += value; - } - else - { - // Store - rConfig.mKeys[key] = value; - } + rConfig.AddKeyValue(key, value); } else { - rErrorMsg += "Invalid key in block "+rConfig.mName+"\n"; + rErrorMsg += "Invalid configuration key: " + line + "\n"; } } else @@ -286,40 +370,60 @@ bool Configuration::LoadInto(Configuration &rConfig, FdGetLine &rGetLine, std::s return true; } +void Configuration::AddKeyValue(const std::string& rKey, + const std::string& rValue) +{ + // Check for duplicate values + if(mKeys.find(rKey) != mKeys.end()) + { + // Multi-values allowed here, but checked later on + mKeys[rKey] += MultiValueSeparator; + mKeys[rKey] += rValue; + } + else + { + // Store + mKeys[rKey] = rValue; + } +} + +void Configuration::AddSubConfig(const std::string& rName, + const Configuration& rSubConfig) +{ + mSubConfigurations.push_back( + std::pair<std::string, Configuration>(rName, rSubConfig)); +} + // -------------------------------------------------------------------------- // // Function -// Name: Configuration::KeyExists(const char *) +// Name: Configuration::KeyExists(const std::string&) // Purpose: Checks to see if a key exists // Created: 2003/07/23 // // -------------------------------------------------------------------------- -bool Configuration::KeyExists(const char *pKeyName) const +bool Configuration::KeyExists(const std::string& rKeyName) const { - if(pKeyName == 0) {THROW_EXCEPTION(CommonException, BadArguments)} - - return mKeys.find(pKeyName) != mKeys.end(); + return mKeys.find(rKeyName) != mKeys.end(); } // -------------------------------------------------------------------------- // // Function -// Name: Configuration::GetKeyValue(const char *) +// Name: Configuration::GetKeyValue(const std::string&) // Purpose: Returns the value of a configuration variable // Created: 2003/07/23 // // -------------------------------------------------------------------------- -const std::string &Configuration::GetKeyValue(const char *pKeyName) const +const std::string &Configuration::GetKeyValue(const std::string& rKeyName) const { - if(pKeyName == 0) {THROW_EXCEPTION(CommonException, BadArguments)} - - std::map<std::string, std::string>::const_iterator i(mKeys.find(pKeyName)); + std::map<std::string, std::string>::const_iterator i(mKeys.find(rKeyName)); if(i == mKeys.end()) { - BOX_ERROR("Missing configuration key: " << pKeyName); + BOX_ERROR("Missing configuration key: " << rKeyName); THROW_EXCEPTION(CommonException, ConfigNoKey) } else @@ -332,16 +436,14 @@ const std::string &Configuration::GetKeyValue(const char *pKeyName) const // -------------------------------------------------------------------------- // // Function -// Name: Configuration::GetKeyValueInt(const char *) +// Name: Configuration::GetKeyValueInt(const std::string& rKeyName) // Purpose: Gets a key value as an integer // Created: 2003/07/23 // // -------------------------------------------------------------------------- -int Configuration::GetKeyValueInt(const char *pKeyName) const +int Configuration::GetKeyValueInt(const std::string& rKeyName) const { - if(pKeyName == 0) {THROW_EXCEPTION(CommonException, BadArguments)} - - std::map<std::string, std::string>::const_iterator i(mKeys.find(pKeyName)); + std::map<std::string, std::string>::const_iterator i(mKeys.find(rKeyName)); if(i == mKeys.end()) { @@ -362,16 +464,14 @@ int Configuration::GetKeyValueInt(const char *pKeyName) const // -------------------------------------------------------------------------- // // Function -// Name: Configuration::GetKeyValueBool(const char *) const +// Name: Configuration::GetKeyValueBool(const std::string&) // Purpose: Gets a key value as a boolean // Created: 17/2/04 // // -------------------------------------------------------------------------- -bool Configuration::GetKeyValueBool(const char *pKeyName) const +bool Configuration::GetKeyValueBool(const std::string& rKeyName) const { - if(pKeyName == 0) {THROW_EXCEPTION(CommonException, BadArguments)} - - std::map<std::string, std::string>::const_iterator i(mKeys.find(pKeyName)); + std::map<std::string, std::string>::const_iterator i(mKeys.find(rKeyName)); if(i == mKeys.end()) { @@ -428,22 +528,21 @@ std::vector<std::string> Configuration::GetKeyNames() const // -------------------------------------------------------------------------- // // Function -// Name: Configuration::SubConfigurationExists(const char *) +// Name: Configuration::SubConfigurationExists(const +// std::string&) // Purpose: Checks to see if a sub configuration exists // Created: 2003/07/23 // // -------------------------------------------------------------------------- -bool Configuration::SubConfigurationExists(const char *pSubName) const +bool Configuration::SubConfigurationExists(const std::string& rSubName) const { - if(pSubName == 0) {THROW_EXCEPTION(CommonException, BadArguments)} - // Attempt to find it... std::list<std::pair<std::string, Configuration> >::const_iterator i(mSubConfigurations.begin()); for(; i != mSubConfigurations.end(); ++i) { // This the one? - if(i->first == pSubName) + if(i->first == rSubName) { // Yes. return true; @@ -458,22 +557,52 @@ bool Configuration::SubConfigurationExists(const char *pSubName) const // -------------------------------------------------------------------------- // // Function -// Name: Configuration::GetSubConfiguration(const char *) +// Name: Configuration::GetSubConfiguration(const +// std::string&) // Purpose: Gets a sub configuration // Created: 2003/07/23 // // -------------------------------------------------------------------------- -const Configuration &Configuration::GetSubConfiguration(const char *pSubName) const +const Configuration &Configuration::GetSubConfiguration(const std::string& + rSubName) const { - if(pSubName == 0) {THROW_EXCEPTION(CommonException, BadArguments)} - // Attempt to find it... std::list<std::pair<std::string, Configuration> >::const_iterator i(mSubConfigurations.begin()); for(; i != mSubConfigurations.end(); ++i) { // This the one? - if(i->first == pSubName) + if(i->first == rSubName) + { + // Yes. + return i->second; + } + } + + THROW_EXCEPTION(CommonException, ConfigNoSubConfig) +} + + +// -------------------------------------------------------------------------- +// +// Function +// Name: Configuration::GetSubConfiguration(const +// std::string&) +// Purpose: Gets a sub configuration for editing +// Created: 2008/08/12 +// +// -------------------------------------------------------------------------- +Configuration &Configuration::GetSubConfigurationEditable(const std::string& + rSubName) +{ + // Attempt to find it... + + for(SubConfigListType::iterator + i = mSubConfigurations.begin(); + i != mSubConfigurations.end(); ++i) + { + // This the one? + if(i->first == rSubName) { // Yes. return i->second; @@ -510,12 +639,14 @@ std::vector<std::string> Configuration::GetSubConfigurationNames() const // -------------------------------------------------------------------------- // // Function -// Name: Configuration::Verify(const Configuration &, const ConfigurationVerify &, const std::string &, std::string &) -// Purpose: Return list of sub configuration names +// Name: Configuration::Verify(const ConfigurationVerify &, const std::string &, std::string &) +// Purpose: Checks that the configuration is valid according to the +// supplied verifier // Created: 2003/07/24 // // -------------------------------------------------------------------------- -bool Configuration::Verify(Configuration &rConfig, const ConfigurationVerify &rVerify, const std::string &rLevel, std::string &rErrorMsg) +bool Configuration::Verify(const ConfigurationVerify &rVerify, + const std::string &rLevel, std::string &rErrorMsg) { bool ok = true; @@ -528,15 +659,14 @@ bool Configuration::Verify(Configuration &rConfig, const ConfigurationVerify &rV do { // Can the key be found? - ASSERT(pvkey->mpName); - if(rConfig.KeyExists(pvkey->mpName)) + if(KeyExists(pvkey->Name())) { // Get value - const std::string &rval = rConfig.GetKeyValue(pvkey->mpName); + const std::string &rval = GetKeyValue(pvkey->Name()); const char *val = rval.c_str(); // Check it's a number? - if((pvkey->Tests & ConfigTest_IsInt) == ConfigTest_IsInt) + if((pvkey->Flags() & ConfigTest_IsInt) == ConfigTest_IsInt) { // Test it... char *end; @@ -545,12 +675,12 @@ bool Configuration::Verify(Configuration &rConfig, const ConfigurationVerify &rV { // not a good value ok = false; - rErrorMsg += rLevel + rConfig.mName +"." + pvkey->mpName + " (key) is not a valid integer.\n"; + rErrorMsg += rLevel + mName + "." + pvkey->Name() + " (key) is not a valid integer.\n"; } } // Check it's a bool? - if((pvkey->Tests & ConfigTest_IsBool) == ConfigTest_IsBool) + if((pvkey->Flags() & ConfigTest_IsBool) == ConfigTest_IsBool) { // See if it's one of the allowed strings. bool found = false; @@ -568,37 +698,38 @@ bool Configuration::Verify(Configuration &rConfig, const ConfigurationVerify &rV if(!found) { ok = false; - rErrorMsg += rLevel + rConfig.mName +"." + pvkey->mpName + " (key) is not a valid boolean value.\n"; + rErrorMsg += rLevel + mName + "." + pvkey->Name() + " (key) is not a valid boolean value.\n"; } } // Check for multi valued statments where they're not allowed - if((pvkey->Tests & ConfigTest_MultiValueAllowed) == 0) + if((pvkey->Flags() & ConfigTest_MultiValueAllowed) == 0) { // Check to see if this key is a multi-value -- it shouldn't be if(rval.find(MultiValueSeparator) != rval.npos) { ok = false; - rErrorMsg += rLevel + rConfig.mName +"." + pvkey->mpName + " (key) multi value not allowed (duplicated key?).\n"; + rErrorMsg += rLevel + mName +"." + pvkey->Name() + " (key) multi value not allowed (duplicated key?).\n"; } } } else { // Is it required to exist? - if((pvkey->Tests & ConfigTest_Exists) == ConfigTest_Exists) + if((pvkey->Flags() & ConfigTest_Exists) == ConfigTest_Exists) { // Should exist, but doesn't. ok = false; - rErrorMsg += rLevel + rConfig.mName + "." + pvkey->mpName + " (key) is missing.\n"; + rErrorMsg += rLevel + mName + "." + pvkey->Name() + " (key) is missing.\n"; } - else if(pvkey->mpDefaultValue) + else if(pvkey->HasDefaultValue()) { - rConfig.mKeys[std::string(pvkey->mpName)] = std::string(pvkey->mpDefaultValue); + mKeys[pvkey->Name()] = + pvkey->DefaultValue(); } } - if((pvkey->Tests & ConfigTest_LastEntry) == ConfigTest_LastEntry) + if((pvkey->Flags() & ConfigTest_LastEntry) == ConfigTest_LastEntry) { // No more! todo = false; @@ -610,22 +741,22 @@ bool Configuration::Verify(Configuration &rConfig, const ConfigurationVerify &rV } while(todo); // Check for additional keys - for(std::map<std::string, std::string>::const_iterator i = rConfig.mKeys.begin(); - i != rConfig.mKeys.end(); ++i) + for(std::map<std::string, std::string>::const_iterator i = mKeys.begin(); + i != mKeys.end(); ++i) { // Is the name in the list? const ConfigurationVerifyKey *scan = rVerify.mpKeys; bool found = false; while(scan) { - if(scan->mpName == i->first) + if(scan->Name() == i->first) { found = true; break; } // Next? - if((scan->Tests & ConfigTest_LastEntry) == ConfigTest_LastEntry) + if((scan->Flags() & ConfigTest_LastEntry) == ConfigTest_LastEntry) { break; } @@ -636,7 +767,7 @@ bool Configuration::Verify(Configuration &rConfig, const ConfigurationVerify &rV { // Shouldn't exist, but does. ok = false; - rErrorMsg += rLevel + rConfig.mName + "." + i->first + " (key) is not a known key. Check spelling and placement.\n"; + rErrorMsg += rLevel + mName + "." + i->first + " (key) is not a known key. Check spelling and placement.\n"; } } } @@ -650,8 +781,7 @@ bool Configuration::Verify(Configuration &rConfig, const ConfigurationVerify &rV const ConfigurationVerify *scan = rVerify.mpSubConfigurations; while(scan) { - ASSERT(scan->mpName); - if(scan->mpName[0] == '*') + if(scan->mName.length() > 0 && scan->mName[0] == '*') { wildcardverify = scan; } @@ -659,24 +789,25 @@ bool Configuration::Verify(Configuration &rConfig, const ConfigurationVerify &rV // Required? if((scan->Tests & ConfigTest_Exists) == ConfigTest_Exists) { - if(scan->mpName[0] == '*') + if(scan->mName.length() > 0 && + scan->mName[0] == '*') { // Check something exists - if(rConfig.mSubConfigurations.size() < 1) + if(mSubConfigurations.size() < 1) { // A sub config should exist, but doesn't. ok = false; - rErrorMsg += rLevel + rConfig.mName + ".* (block) is missing (a block must be present).\n"; + rErrorMsg += rLevel + mName + ".* (block) is missing (a block must be present).\n"; } } else { // Check real thing exists - if(!rConfig.SubConfigurationExists(scan->mpName)) + if(!SubConfigurationExists(scan->mName)) { // Should exist, but doesn't. ok = false; - rErrorMsg += rLevel + rConfig.mName + "." + scan->mpName + " (block) is missing.\n"; + rErrorMsg += rLevel + mName + "." + scan->mName + " (block) is missing.\n"; } } } @@ -690,8 +821,9 @@ bool Configuration::Verify(Configuration &rConfig, const ConfigurationVerify &rV } // Go through the sub configurations, one by one - for(std::list<std::pair<std::string, Configuration> >::const_iterator i(rConfig.mSubConfigurations.begin()); - i != rConfig.mSubConfigurations.end(); ++i) + for(SubConfigListType::iterator + i = mSubConfigurations.begin(); + i != mSubConfigurations.end(); ++i) { // Can this be found? const ConfigurationVerify *subverify = 0; @@ -701,7 +833,7 @@ bool Configuration::Verify(Configuration &rConfig, const ConfigurationVerify &rV ASSERT(name); while(scan) { - if(strcmp(scan->mpName, name) == 0) + if(scan->mName == name) { // found it! subverify = scan; @@ -725,7 +857,8 @@ bool Configuration::Verify(Configuration &rConfig, const ConfigurationVerify &rV if(subverify) { // override const-ness here... - if(!Verify((Configuration&)i->second, *subverify, rConfig.mName + '.', rErrorMsg)) + if(!i->second.Verify(*subverify, mName + '.', + rErrorMsg)) { ok = false; } |