diff --git a/Util/include/Poco/Util/AbstractConfiguration.h b/Util/include/Poco/Util/AbstractConfiguration.h index 9f1e48d6e8..9e5d56553c 100644 --- a/Util/include/Poco/Util/AbstractConfiguration.h +++ b/Util/include/Poco/Util/AbstractConfiguration.h @@ -125,14 +125,14 @@ class Util_API AbstractConfiguration: public Poco::RefCountedObject std::string getString(const std::string& key) const; /// Returns the string value of the property with the given name. /// Throws a NotFoundException if the key does not exist. - /// If the value contains references to other properties (${}), these - /// are expanded. + /// If the value contains references to other properties (${}, or + /// ${:-}), these are expanded (see expand()). std::string getString(const std::string& key, const std::string& defaultValue) const; /// If a property with the given key exists, returns the property's string value, /// otherwise returns the given default value. - /// If the value contains references to other properties (${}), these - /// are expanded. + /// If the value contains references to other properties (${}, or + /// ${:-}), these are expanded (see expand()). std::string getRawString(const std::string& key) const; /// Returns the raw string value of the property with the given name. @@ -150,8 +150,8 @@ class Util_API AbstractConfiguration: public Poco::RefCountedObject /// Throws a SyntaxException if the property can not be converted /// to an int. /// Numbers starting with 0x are treated as hexadecimal. - /// If the value contains references to other properties (${}), these - /// are expanded. + /// If the value contains references to other properties (${}, or + /// ${:-}), these are expanded (see expand()). unsigned int getUInt(const std::string& key) const; /// Returns the unsigned int value of the property with the given name. @@ -159,8 +159,8 @@ class Util_API AbstractConfiguration: public Poco::RefCountedObject /// Throws a SyntaxException if the property can not be converted /// to an unsigned int. /// Numbers starting with 0x are treated as hexadecimal. - /// If the value contains references to other properties (${}), these - /// are expanded. + /// If the value contains references to other properties (${}, or + /// ${:-}), these are expanded (see expand()). int getInt(const std::string& key, int defaultValue) const; /// If a property with the given key exists, returns the property's int value, @@ -168,8 +168,8 @@ class Util_API AbstractConfiguration: public Poco::RefCountedObject /// Throws a SyntaxException if the property can not be converted /// to an int. /// Numbers starting with 0x are treated as hexadecimal. - /// If the value contains references to other properties (${}), these - /// are expanded. + /// If the value contains references to other properties (${}, or + /// ${:-}), these are expanded (see expand()). unsigned int getUInt(const std::string& key, unsigned int defaultValue) const; /// If a property with the given key exists, returns the property's unsigned int @@ -177,8 +177,8 @@ class Util_API AbstractConfiguration: public Poco::RefCountedObject /// Throws a SyntaxException if the property can not be converted /// to an unsigned int. /// Numbers starting with 0x are treated as hexadecimal. - /// If the value contains references to other properties (${}), these - /// are expanded. + /// If the value contains references to other properties (${}, or + /// ${:-}), these are expanded (see expand()). Poco::Int32 getInt32(const std::string& key) const; /// Returns the 32-bit int value of the property with the given name. @@ -186,8 +186,8 @@ class Util_API AbstractConfiguration: public Poco::RefCountedObject /// Throws a SyntaxException if the property can not be converted /// to an Int32. /// Numbers starting with 0x are treated as hexadecimal. - /// If the value contains references to other properties (${}), these - /// are expanded. + /// If the value contains references to other properties (${}, or + /// ${:-}), these are expanded (see expand()). Poco::UInt32 getUInt32(const std::string& key) const; /// Returns the 32-bit unsigned int value of the property with the given name. @@ -195,8 +195,8 @@ class Util_API AbstractConfiguration: public Poco::RefCountedObject /// Throws a SyntaxException if the property can not be converted /// to an UInt32. /// Numbers starting with 0x are treated as hexadecimal. - /// If the value contains references to other properties (${}), these - /// are expanded. + /// If the value contains references to other properties (${}, or + /// ${:-}), these are expanded (see expand()). Poco::Int32 getInt32(const std::string& key, Poco::Int32 defaultValue) const; /// If a property with the given key exists, returns the property's 32-bit int value, @@ -204,8 +204,8 @@ class Util_API AbstractConfiguration: public Poco::RefCountedObject /// Throws a SyntaxException if the property can not be converted /// to an Int32. /// Numbers starting with 0x are treated as hexadecimal. - /// If the value contains references to other properties (${}), these - /// are expanded. + /// If the value contains references to other properties (${}, or + /// ${:-}), these are expanded (see expand()). Poco::UInt32 getUInt32(const std::string& key, Poco::UInt32 defaultValue) const; /// If a property with the given key exists, returns the property's 32-bit unsigned int @@ -213,8 +213,8 @@ class Util_API AbstractConfiguration: public Poco::RefCountedObject /// Throws a SyntaxException if the property can not be converted /// to an UInt32. /// Numbers starting with 0x are treated as hexadecimal. - /// If the value contains references to other properties (${}), these - /// are expanded. + /// If the value contains references to other properties (${}, or + /// ${:-}), these are expanded (see expand()). Poco::Int16 getInt16(const std::string& key) const; /// Returns the 16-bit int value of the property with the given name. @@ -222,8 +222,8 @@ class Util_API AbstractConfiguration: public Poco::RefCountedObject /// Throws a SyntaxException or a RangeException if the property can not be converted /// to an Int16. /// Numbers starting with 0x are treated as hexadecimal. - /// If the value contains references to other properties (${}), these - /// are expanded. + /// If the value contains references to other properties (${}, or + /// ${:-}), these are expanded (see expand()). Poco::UInt16 getUInt16(const std::string& key) const; /// Returns the unsigned 16-bit int value of the property with the given name. @@ -231,8 +231,8 @@ class Util_API AbstractConfiguration: public Poco::RefCountedObject /// Throws a SyntaxException or a RangeException if the property can not be converted /// to an UInt16. /// Numbers starting with 0x are treated as hexadecimal. - /// If the value contains references to other properties (${}), these - /// are expanded. + /// If the value contains references to other properties (${}, or + /// ${:-}), these are expanded (see expand()). Poco::Int16 getInt16(const std::string& key, Poco::Int16 defaultValue) const; /// If a property with the given key exists, returns the property's 16-bit int value, @@ -240,8 +240,8 @@ class Util_API AbstractConfiguration: public Poco::RefCountedObject /// Throws a SyntaxException or a RangeException if the property can not be converted /// to an Int16. /// Numbers starting with 0x are treated as hexadecimal. - /// If the value contains references to other properties (${}), these - /// are expanded. + /// If the value contains references to other properties (${}, or + /// ${:-}), these are expanded (see expand()). Poco::UInt16 getUInt16(const std::string& key, Poco::UInt16 defaultValue) const; /// If a property with the given key exists, returns the property's unsigned 16-bit int @@ -249,8 +249,8 @@ class Util_API AbstractConfiguration: public Poco::RefCountedObject /// Throws a SyntaxException or a RangeException if the property can not be converted /// to an UInt16. /// Numbers starting with 0x are treated as hexadecimal. - /// If the value contains references to other properties (${}), these - /// are expanded. + /// If the value contains references to other properties (${}, or + /// ${:-}), these are expanded (see expand()). #if defined(POCO_HAVE_INT64) @@ -260,8 +260,8 @@ class Util_API AbstractConfiguration: public Poco::RefCountedObject /// Throws a SyntaxException if the property can not be converted /// to an Int64. /// Numbers starting with 0x are treated as hexadecimal. - /// If the value contains references to other properties (${}), these - /// are expanded. + /// If the value contains references to other properties (${}, or + /// ${:-}), these are expanded (see expand()). UInt64 getUInt64(const std::string& key) const; /// Returns the UInt64 value of the property with the given name. @@ -269,8 +269,8 @@ class Util_API AbstractConfiguration: public Poco::RefCountedObject /// Throws a SyntaxException if the property can not be converted /// to an UInt64. /// Numbers starting with 0x are treated as hexadecimal. - /// If the value contains references to other properties (${}), these - /// are expanded. + /// If the value contains references to other properties (${}, or + /// ${:-}), these are expanded (see expand()). Int64 getInt64(const std::string& key, Int64 defaultValue) const; /// If a property with the given key exists, returns the property's Int64 value, @@ -278,8 +278,8 @@ class Util_API AbstractConfiguration: public Poco::RefCountedObject /// Throws a SyntaxException if the property can not be converted /// to an Int64. /// Numbers starting with 0x are treated as hexadecimal. - /// If the value contains references to other properties (${}), these - /// are expanded. + /// If the value contains references to other properties (${}, or + /// ${:-}), these are expanded (see expand()). UInt64 getUInt64(const std::string& key, UInt64 defaultValue) const; /// If a property with the given key exists, returns the property's UInt64 @@ -287,8 +287,8 @@ class Util_API AbstractConfiguration: public Poco::RefCountedObject /// Throws a SyntaxException if the property can not be converted /// to an UInt64. /// Numbers starting with 0x are treated as hexadecimal. - /// If the value contains references to other properties (${}), these - /// are expanded. + /// If the value contains references to other properties (${}, or + /// ${:-}), these are expanded (see expand()). #endif // defined(POCO_HAVE_INT64) @@ -297,24 +297,24 @@ class Util_API AbstractConfiguration: public Poco::RefCountedObject /// Throws a NotFoundException if the key does not exist. /// Throws a SyntaxException if the property can not be converted /// to a double. - /// If the value contains references to other properties (${}), these - /// are expanded. + /// If the value contains references to other properties (${}, or + /// ${:-}), these are expanded (see expand()). double getDouble(const std::string& key, double defaultValue) const; /// If a property with the given key exists, returns the property's double value, /// otherwise returns the given default value. /// Throws a SyntaxException if the property can not be converted /// to an double. - /// If the value contains references to other properties (${}), these - /// are expanded. + /// If the value contains references to other properties (${}, or + /// ${:-}), these are expanded (see expand()). bool getBool(const std::string& key) const; /// Returns the boolean value of the property with the given name. /// Throws a NotFoundException if the key does not exist. /// Throws a SyntaxException if the property can not be converted /// to a boolean. - /// If the value contains references to other properties (${}), these - /// are expanded. + /// If the value contains references to other properties (${}, or + /// ${:-}), these are expanded (see expand()). bool getBool(const std::string& key, bool defaultValue) const; /// If a property with the given key exists, returns the property's boolean value, @@ -325,8 +325,8 @@ class Util_API AbstractConfiguration: public Poco::RefCountedObject /// - numerical values: non zero becomes true, zero becomes false /// - strings: true, yes, on become true, false, no, off become false /// Case does not matter. - /// If the value contains references to other properties (${}), these - /// are expanded. + /// If the value contains references to other properties (${}, or + /// ${:-}), these are expanded (see expand()). virtual void setString(const std::string& key, const std::string& value); /// Sets the property with the given key to the given value. @@ -394,6 +394,12 @@ class Util_API AbstractConfiguration: public Poco::RefCountedObject /// value of the . If does not exist, /// nothing is changed. /// + /// It is also possible to specify a default value for a referenced + /// property that does not exist, using ${:-}. + /// Note that currently a default value cannot contain a closing + /// curly bracket ("}"). The default value also cannot reference + /// another variable. + /// /// If a circular property reference is detected, a /// CircularReferenceException will be thrown. diff --git a/Util/src/AbstractConfiguration.cpp b/Util/src/AbstractConfiguration.cpp index df17ff4053..d8a41ff030 100644 --- a/Util/src/AbstractConfiguration.cpp +++ b/Util/src/AbstractConfiguration.cpp @@ -507,13 +507,33 @@ std::string AbstractConfiguration::uncheckedExpand(const std::string& value) con { ++it; std::string prop; - while (it != end && *it != '}') prop += *it++; + std::string deflt; + bool haveDefault = false; + while (it != end && *it != '}') + { + if (*it == ':') + { + ++it; + if (it != end && *it == '-') + { + haveDefault = true; + ++it; + while (it != end && *it != '}') deflt += *it++; + } + else prop += ':'; + } + else prop += *it++; + } if (it != end) ++it; std::string value; if (getRaw(prop, value)) { result.append(internalExpand(value)); } + else if (haveDefault) + { + result.append(deflt); + } else { result.append("${"); diff --git a/Util/testsuite/src/AbstractConfigurationTest.cpp b/Util/testsuite/src/AbstractConfigurationTest.cpp index 55e3b86047..1e6ab7ec3b 100644 --- a/Util/testsuite/src/AbstractConfigurationTest.cpp +++ b/Util/testsuite/src/AbstractConfigurationTest.cpp @@ -105,6 +105,49 @@ void AbstractConfigurationTest::testGetInt() } +void AbstractConfigurationTest::testGetInt16() +{ + AutoPtr pConf = createConfiguration(); + + assertTrue (pConf->getInt16("prop4.int1") == 42); + assertTrue (pConf->getInt16("prop4.int2") == -42); + assertTrue (pConf->getInt16("prop4.hex") == 0x1f); + assertTrue (pConf->getUInt16("prop4.hex") == 0x1f); + assertTrue (pConf->getInt16("ref2") == 42); + + try + { + pConf->getInt16("prop1"); + fail("not a number - must throw"); + } + catch (Poco::SyntaxException&) + { + } + + try + { + pConf->getInt16("prop4.notint16"); + fail("too big for UInt16 - must throw"); + } + catch (Poco::RangeException&) + { + } + + try + { + pConf->getUInt16("prop4.notuint16"); + fail("too big for UInt16 - must throw"); + } + catch (Poco::RangeException&) + { + } + + assertTrue (pConf->getInt16("prop4.int1", 100) == 42); + assertTrue (pConf->getInt16("prop4.int2", 100) == -42); + assertTrue (pConf->getInt16("prop4.int3", 100) == 100); +} + + void AbstractConfigurationTest::testGetInt64() { #if defined(POCO_HAVE_INT64) @@ -212,6 +255,11 @@ void AbstractConfigurationTest::testExpand() assertTrue (pConf->getString("dollar.atend") == "foo$"); assertTrue (pConf->getString("dollar.middle") == "foo$bar"); + + assertTrue (pConf->expand("default=${undefined:-default value}") == "default=default value"); + assertTrue (pConf->expand("default=${undefined:-}") == "default="); + assertTrue (pConf->expand("default=${undefined:value}") == "default=${undefined:value}"); + assertTrue (pConf->expand("default:${undefined::value}") == "default:${undefined::value}"); } @@ -368,7 +416,7 @@ void AbstractConfigurationTest::testRemove() pConf->keys(keys); assertTrue (keys.size() == 13); pConf->keys("prop4", keys); - assertTrue (keys.size() == 17); + assertTrue (keys.size() == 19); pConf->remove("prop4.bool1"); assertTrue (!pConf->hasProperty("prop4.bool1")); @@ -377,7 +425,7 @@ void AbstractConfigurationTest::testRemove() pConf->keys(keys); assertTrue (keys.size() == 13); pConf->keys("prop4", keys); - assertTrue (keys.size() == 16); + assertTrue (keys.size() == 18); pConf->remove("prop4"); assertTrue (!pConf->hasProperty("prop4.bool1")); @@ -406,6 +454,8 @@ AbstractConfiguration::Ptr AbstractConfigurationTest::createConfiguration() cons pConfig->setString("prop4.int1", "42"); pConfig->setString("prop4.int2", "-42"); pConfig->setString("prop4.uint", NumberFormatter::format(std::numeric_limits::max())); + pConfig->setString("prop4.notint16", "32768"); + pConfig->setString("prop4.notuint16", "65536"); #if defined(POCO_HAVE_INT64) pConfig->setString("prop4.bigint1", NumberFormatter::format(std::numeric_limits::max())); pConfig->setString("prop4.bigint2", NumberFormatter::format(std::numeric_limits::min())); diff --git a/Util/testsuite/src/AbstractConfigurationTest.h b/Util/testsuite/src/AbstractConfigurationTest.h index f083c08446..9de998dc3b 100644 --- a/Util/testsuite/src/AbstractConfigurationTest.h +++ b/Util/testsuite/src/AbstractConfigurationTest.h @@ -29,6 +29,7 @@ class AbstractConfigurationTest: public CppUnit::TestCase void testHasProperty(); void testGetString(); void testGetInt(); + void testGetInt16(); void testGetInt64(); void testGetDouble(); void testGetBool(); diff --git a/Util/testsuite/src/IniFileConfigurationTest.cpp b/Util/testsuite/src/IniFileConfigurationTest.cpp index 4c47574baa..cf005f280a 100644 --- a/Util/testsuite/src/IniFileConfigurationTest.cpp +++ b/Util/testsuite/src/IniFileConfigurationTest.cpp @@ -102,7 +102,7 @@ void IniFileConfigurationTest::testCaseInsensitiveRemove() pConf->keys(keys); assertTrue (keys.size() == 13); pConf->keys("prop4", keys); - assertTrue (keys.size() == 17); + assertTrue (keys.size() == 19); pConf->remove("PROP4.Bool1"); assertTrue (pConf->hasProperty("Prop1")); @@ -112,7 +112,7 @@ void IniFileConfigurationTest::testCaseInsensitiveRemove() pConf->keys(keys); assertTrue (keys.size() == 13); pConf->keys("PROP4", keys); - assertTrue (keys.size() == 16); + assertTrue (keys.size() == 18); pConf->remove("Prop4"); assertTrue (pConf->hasProperty("Prop1"));