summaryrefslogtreecommitdiff
path: root/lib/common/Configuration.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/common/Configuration.cpp')
-rw-r--r--lib/common/Configuration.cpp335
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;
}