Skip to content

Commit

Permalink
#4173: AbstractConfiguration: when expanding property references, all…
Browse files Browse the repository at this point in the history
…ow specifying a default value; #4174: AbstractConfiguration: support Int16/UInt16 and Int32/UInt32
  • Loading branch information
obiltschnig committed Sep 30, 2023
1 parent 6797e78 commit 20279ae
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 49 deletions.
94 changes: 50 additions & 44 deletions Util/include/Poco/Util/AbstractConfiguration.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 (${<property>}), these
/// are expanded.
/// If the value contains references to other properties (${<property>}, or
/// ${<property>:-<default>}), 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 (${<property>}), these
/// are expanded.
/// If the value contains references to other properties (${<property>}, or
/// ${<property>:-<default>}), 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.
Expand All @@ -150,107 +150,107 @@ 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 (${<property>}), these
/// are expanded.
/// If the value contains references to other properties (${<property>}, or
/// ${<property>:-<default>}), 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.
/// Throws a NotFoundException if the key does not exist.
/// 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 (${<property>}), these
/// are expanded.
/// If the value contains references to other properties (${<property>}, or
/// ${<property>:-<default>}), 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,
/// otherwise returns the given default value.
/// 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 (${<property>}), these
/// are expanded.
/// If the value contains references to other properties (${<property>}, or
/// ${<property>:-<default>}), 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
/// value, otherwise returns the given default value.
/// 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 (${<property>}), these
/// are expanded.
/// If the value contains references to other properties (${<property>}, or
/// ${<property>:-<default>}), 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 (${<property>}), these
/// are expanded.
/// If the value contains references to other properties (${<property>}, or
/// ${<property>:-<default>}), 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 (${<property>}), these
/// are expanded.
/// If the value contains references to other properties (${<property>}, or
/// ${<property>:-<default>}), 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 (${<property>}), these
/// are expanded.
/// If the value contains references to other properties (${<property>}, or
/// ${<property>:-<default>}), 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 (${<property>}), these
/// are expanded.
/// If the value contains references to other properties (${<property>}, or
/// ${<property>:-<default>}), 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 (${<property>}), these
/// are expanded.
/// If the value contains references to other properties (${<property>}, or
/// ${<property>:-<default>}), 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 (${<property>}), these
/// are expanded.
/// If the value contains references to other properties (${<property>}, or
/// ${<property>:-<default>}), 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 (${<property>}), these
/// are expanded.
/// If the value contains references to other properties (${<property>}, or
/// ${<property>:-<default>}), 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 (${<property>}), these
/// are expanded.
/// If the value contains references to other properties (${<property>}, or
/// ${<property>:-<default>}), these are expanded (see expand()).

#if defined(POCO_HAVE_INT64)

Expand All @@ -260,35 +260,35 @@ 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 (${<property>}), these
/// are expanded.
/// If the value contains references to other properties (${<property>}, or
/// ${<property>:-<default>}), these are expanded (see expand()).

UInt64 getUInt64(const std::string& key) const;
/// Returns the UInt64 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 UInt64.
/// Numbers starting with 0x are treated as hexadecimal.
/// If the value contains references to other properties (${<property>}), these
/// are expanded.
/// If the value contains references to other properties (${<property>}, or
/// ${<property>:-<default>}), 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,
/// otherwise returns the given default value.
/// 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 (${<property>}), these
/// are expanded.
/// If the value contains references to other properties (${<property>}, or
/// ${<property>:-<default>}), 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
/// value, otherwise returns the given default value.
/// 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 (${<property>}), these
/// are expanded.
/// If the value contains references to other properties (${<property>}, or
/// ${<property>:-<default>}), these are expanded (see expand()).

#endif // defined(POCO_HAVE_INT64)

Expand All @@ -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 (${<property>}), these
/// are expanded.
/// If the value contains references to other properties (${<property>}, or
/// ${<property>:-<default>}), 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 (${<property>}), these
/// are expanded.
/// If the value contains references to other properties (${<property>}, or
/// ${<property>:-<default>}), 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 (${<property>}), these
/// are expanded.
/// If the value contains references to other properties (${<property>}, or
/// ${<property>:-<default>}), 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,
Expand All @@ -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 (${<property>}), these
/// are expanded.
/// If the value contains references to other properties (${<property>}, or
/// ${<property>:-<default>}), 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.
Expand Down Expand Up @@ -394,6 +394,12 @@ class Util_API AbstractConfiguration: public Poco::RefCountedObject
/// value of the <property>. If <property> does not exist,
/// nothing is changed.
///
/// It is also possible to specify a default value for a referenced
/// property that does not exist, using ${<property>:-<default>}.
/// 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.

Expand Down
22 changes: 21 additions & 1 deletion Util/src/AbstractConfiguration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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("${");
Expand Down
54 changes: 52 additions & 2 deletions Util/testsuite/src/AbstractConfigurationTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,49 @@ void AbstractConfigurationTest::testGetInt()
}


void AbstractConfigurationTest::testGetInt16()
{
AutoPtr<AbstractConfiguration> 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)
Expand Down Expand Up @@ -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}");
}


Expand Down Expand Up @@ -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"));
Expand All @@ -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"));
Expand Down Expand Up @@ -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<unsigned>::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<Int64>::max()));
pConfig->setString("prop4.bigint2", NumberFormatter::format(std::numeric_limits<Int64>::min()));
Expand Down
1 change: 1 addition & 0 deletions Util/testsuite/src/AbstractConfigurationTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class AbstractConfigurationTest: public CppUnit::TestCase
void testHasProperty();
void testGetString();
void testGetInt();
void testGetInt16();
void testGetInt64();
void testGetDouble();
void testGetBool();
Expand Down
4 changes: 2 additions & 2 deletions Util/testsuite/src/IniFileConfigurationTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"));
Expand All @@ -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"));
Expand Down

0 comments on commit 20279ae

Please sign in to comment.