diff --git a/Util/include/Poco/Util/AbstractConfiguration.h b/Util/include/Poco/Util/AbstractConfiguration.h index 42aec09b3..4c10a9c79 100644 --- a/Util/include/Poco/Util/AbstractConfiguration.h +++ b/Util/include/Poco/Util/AbstractConfiguration.h @@ -125,14 +125,14 @@ public: 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 @@ public: /// 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 @@ public: /// 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 @@ public: /// 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,80 @@ public: /// 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. + /// Throws a NotFoundException if the key does not exist. + /// 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 (${}, 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. + /// Throws a NotFoundException if the key does not exist. + /// 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 (${}, 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, + /// otherwise returns the given default value. + /// 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 (${}, 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 + /// value, otherwise returns the given default value. + /// 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 (${}, 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. + /// Throws a NotFoundException if the key does not exist. + /// 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 (${}, 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. + /// Throws a NotFoundException if the key does not exist. + /// 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 (${}, 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, + /// otherwise returns the given default value. + /// 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 (${}, 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 + /// value, otherwise returns the given default value. + /// 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 (${}, or + /// ${:-}), these are expanded (see expand()). #if defined(POCO_HAVE_INT64) @@ -188,8 +260,8 @@ public: /// 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. @@ -197,8 +269,8 @@ public: /// 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, @@ -206,8 +278,8 @@ public: /// 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 @@ -215,8 +287,8 @@ public: /// 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) @@ -225,24 +297,24 @@ public: /// 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, @@ -253,8 +325,8 @@ public: /// - 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. @@ -268,6 +340,22 @@ public: /// Sets the property with the given key to the given value. /// An already existing value for the key is overwritten. + virtual void setInt16(const std::string& key, Poco::Int16 value); + /// Sets the property with the given key to the given value. + /// An already existing value for the key is overwritten. + + virtual void setUInt16(const std::string& key, Poco::UInt16 value); + /// Sets the property with the given key to the given value. + /// An already existing value for the key is overwritten. + + virtual void setInt32(const std::string& key, Poco::Int32 value); + /// Sets the property with the given key to the given value. + /// An already existing value for the key is overwritten. + + virtual void setUInt32(const std::string& key, Poco::UInt32 value); + /// Sets the property with the given key to the given value. + /// An already existing value for the key is overwritten. + #if defined(POCO_HAVE_INT64) virtual void setInt64(const std::string& key, Int64 value); @@ -312,6 +400,12 @@ public: /// 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. @@ -359,6 +453,14 @@ protected: /// Returns string as unsigned integer. /// Decimal and hexadecimal notation is supported. + static Poco::Int16 parseInt16(const std::string& value); + /// Returns string as signed 16-bit integer. + /// Decimal and hexadecimal notation is supported. + + static Poco::UInt16 parseUInt16(const std::string& value); + /// Returns string as unsigned 16-bit integer. + /// Decimal and hexadecimal notation is supported. + #if defined(POCO_HAVE_INT64) static Int64 parseInt64(const std::string& value); @@ -394,6 +496,35 @@ private: }; +// +// inlines +// + + +inline Poco::Int32 AbstractConfiguration::getInt32(const std::string& key) const +{ + return getInt(key); +} + + +inline Poco::Int32 AbstractConfiguration::getInt32(const std::string& key, Poco::Int32 defaultValue) const +{ + return getInt(key, defaultValue); +} + + +inline Poco::UInt32 AbstractConfiguration::getUInt32(const std::string& key) const +{ + return getUInt(key); +} + + +inline Poco::UInt32 AbstractConfiguration::getUInt32(const std::string& key, Poco::UInt32 defaultValue) const +{ + return getUInt(key, defaultValue); +} + + } } // namespace Poco::Util diff --git a/Util/src/AbstractConfiguration.cpp b/Util/src/AbstractConfiguration.cpp index bdb854f64..2533c40aa 100644 --- a/Util/src/AbstractConfiguration.cpp +++ b/Util/src/AbstractConfiguration.cpp @@ -164,6 +164,54 @@ unsigned AbstractConfiguration::getUInt(const std::string& key, unsigned default } +Poco::Int16 AbstractConfiguration::getInt16(const std::string& key) const +{ + Mutex::ScopedLock lock(_mutex); + + std::string value; + if (getRaw(key, value)) + return parseInt16(internalExpand(value)); + else + throw NotFoundException(key); +} + + +Poco::Int16 AbstractConfiguration::getInt16(const std::string& key, Poco::Int16 defaultValue) const +{ + Mutex::ScopedLock lock(_mutex); + + std::string value; + if (getRaw(key, value)) + return parseInt16(internalExpand(value)); + else + return defaultValue; +} + + +Poco::UInt16 AbstractConfiguration::getUInt16(const std::string& key) const +{ + Mutex::ScopedLock lock(_mutex); + + std::string value; + if (getRaw(key, value)) + return parseUInt16(internalExpand(value)); + else + throw NotFoundException(key); +} + + +Poco::UInt16 AbstractConfiguration::getUInt16(const std::string& key, Poco::UInt16 defaultValue) const +{ + Mutex::ScopedLock lock(_mutex); + + std::string value; + if (getRaw(key, value)) + return parseUInt16(internalExpand(value)); + else + return defaultValue; +} + + #if defined(POCO_HAVE_INT64) @@ -284,6 +332,30 @@ void AbstractConfiguration::setUInt(const std::string& key, unsigned int value) } +void AbstractConfiguration::setInt16(const std::string& key, Poco::Int16 value) +{ + setRawWithEvent(key, NumberFormatter::format(value)); +} + + +void AbstractConfiguration::setUInt16(const std::string& key, Poco::UInt16 value) +{ + setRawWithEvent(key, NumberFormatter::format(value)); +} + + +void AbstractConfiguration::setInt32(const std::string& key, Poco::Int32 value) +{ + setRawWithEvent(key, NumberFormatter::format(value)); +} + + +void AbstractConfiguration::setUInt32(const std::string& key, Poco::UInt32 value) +{ + setRawWithEvent(key, NumberFormatter::format(value)); +} + + #if defined(POCO_HAVE_INT64) @@ -448,13 +520,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("${"); @@ -488,6 +580,34 @@ unsigned AbstractConfiguration::parseUInt(const std::string& value) } +Poco::Int16 AbstractConfiguration::parseInt16(const std::string& value) +{ + int intValue = 0; + if ((value.compare(0, 2, "0x") == 0) || (value.compare(0, 2, "0X") == 0)) + intValue = static_cast(NumberParser::parseHex(value)); + else + intValue = NumberParser::parse(value); + if (intValue >= -32768 && intValue <= 32767) + return static_cast(intValue); + else + throw Poco::RangeException("Not a valid 16-bit integer value", value); +} + + +Poco::UInt16 AbstractConfiguration::parseUInt16(const std::string& value) +{ + unsigned uintValue; + if ((value.compare(0, 2, "0x") == 0) || (value.compare(0, 2, "0X") == 0)) + uintValue = NumberParser::parseHex(value); + else + uintValue = NumberParser::parseUnsigned(value); + if (uintValue <= 65535) + return static_cast(uintValue); + else + throw Poco::RangeException("Not a valid unsigned 16-bit integer value", value); +} + + Int64 AbstractConfiguration::parseInt64(const std::string& value) { if ((value.compare(0, 2, "0x") == 0) || (value.compare(0, 2, "0X") == 0)) diff --git a/Util/testsuite/src/AbstractConfigurationTest.cpp b/Util/testsuite/src/AbstractConfigurationTest.cpp index dfddfeb16..44a78342b 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 5fa9568d0..79fdd4d39 100644 --- a/Util/testsuite/src/AbstractConfigurationTest.h +++ b/Util/testsuite/src/AbstractConfigurationTest.h @@ -29,6 +29,7 @@ public: 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 b27e9732b..9d0243579 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"));