util: Add SettingTo<Int>() and GetArg<Int>()
What changed, and why it matters
This commit is a routine internal code cleanup in Bitcoin Core. It replaces a hardcoded integer-parsing helper with a generic template that can handle several integer sizes, and keeps the old function names as thin wrappers so existing code keeps working. There is no user-facing change and no security fix.
No action required. Treat as normal refactoring.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The change refactors ArgsManager::GetIntArg and SettingToInt into templated GetArg
Changed components
src/common/args.cppsrc/common/args.hsrc/test/getarg_tests.cppInspect captured patch +65 / −16
diff --git a/src/common/args.cpp b/src/common/args.cpp
index 3ffa4d3f..5c8589cf 100644
--- a/src/common/args.cpp
+++ b/src/common/args.cpp
@@ -483,29 +483,33 @@ std::string SettingToString(const common::SettingsValue& value, const std::strin
return SettingToString(value).value_or(strDefault);
}
-int64_t ArgsManager::GetIntArg(const std::string& strArg, int64_t nDefault) const
+template <std::integral Int>
+Int ArgsManager::GetArg(const std::string& strArg, Int nDefault) const
{
- return GetIntArg(strArg).value_or(nDefault);
+ return GetArg<Int>(strArg).value_or(nDefault);
}
-std::optional<int64_t> ArgsManager::GetIntArg(const std::string& strArg) const
+template <std::integral Int>
+std::optional<Int> ArgsManager::GetArg(const std::string& strArg) const
{
const common::SettingsValue value = GetSetting(strArg);
- return SettingToInt(value);
+ return SettingTo<Int>(value);
}
-std::optional<int64_t> SettingToInt(const common::SettingsValue& value)
+template <std::integral Int>
+std::optional<Int> SettingTo(const common::SettingsValue& value)
{
if (value.isNull()) return std::nullopt;
if (value.isFalse()) return 0;
if (value.isTrue()) return 1;
- if (value.isNum()) return value.getInt<int64_t>();
- return LocaleIndependentAtoi<int64_t>(value.get_str());
+ if (value.isNum()) return value.getInt<Int>();
+ return LocaleIndependentAtoi<Int>(value.get_str());
}
-int64_t SettingToInt(const common::SettingsValue& value, int64_t nDefault)
+template <std::integral Int>
+Int SettingTo(const common::SettingsValue& value, Int nDefault)
{
- return SettingToInt(value).value_or(nDefault);
+ return SettingTo<Int>(value).value_or(nDefault);
}
bool ArgsManager::GetBoolArg(const std::string& strArg, bool fDefault) const
@@ -531,6 +535,23 @@ bool SettingToBool(const common::SettingsValue& value, bool fDefault)
return SettingToBool(value).value_or(fDefault);
}
+#define INSTANTIATE_INT_TYPE(Type) \
+ template Type ArgsManager::GetArg<Type>(const std::string&, Type) const; \
+ template std::optional<Type> ArgsManager::GetArg<Type>(const std::string&) const; \
+ template Type SettingTo<Type>(const common::SettingsValue&, Type); \
+ template std::optional<Type> SettingTo<Type>(const common::SettingsValue&)
+
+INSTANTIATE_INT_TYPE(int8_t);
+INSTANTIATE_INT_TYPE(uint8_t);
+INSTANTIATE_INT_TYPE(int16_t);
+INSTANTIATE_INT_TYPE(uint16_t);
+INSTANTIATE_INT_TYPE(int32_t);
+INSTANTIATE_INT_TYPE(uint32_t);
+INSTANTIATE_INT_TYPE(int64_t);
+INSTANTIATE_INT_TYPE(uint64_t);
+
+#undef INSTANTIATE_INT_TYPE
+
bool ArgsManager::SoftSetArg(const std::string& strArg, const std::string& strValue)
{
LOCK(cs_args);
diff --git a/src/common/args.h b/src/common/args.h
index 1b9233ec..477f2cbf 100644
--- a/src/common/args.h
+++ b/src/common/args.h
@@ -11,6 +11,7 @@
#include <util/chaintype.h>
#include <util/fs.h>
+#include <concepts>
#include <cstdint>
#include <iosfwd>
#include <list>
@@ -89,8 +90,14 @@ struct SectionInfo {
std::string SettingToString(const common::SettingsValue&, const std::string&);
std::optional<std::string> SettingToString(const common::SettingsValue&);
-int64_t SettingToInt(const common::SettingsValue&, int64_t);
-std::optional<int64_t> SettingToInt(const common::SettingsValue&);
+template <std::integral Int>
+Int SettingTo(const common::SettingsValue&, Int);
+
+template <std::integral Int>
+std::optional<Int> SettingTo(const common::SettingsValue&);
+
+inline int64_t SettingToInt(const common::SettingsValue& value, int64_t nDefault) { return SettingTo<int64_t>(value, nDefault); }
+inline std::optional<int64_t> SettingToInt(const common::SettingsValue& value) { return SettingTo<int64_t>(value); }
bool SettingToBool(const common::SettingsValue&, bool);
std::optional<bool> SettingToBool(const common::SettingsValue&);
@@ -293,8 +300,14 @@ protected:
* @param nDefault (e.g. 1)
* @return command-line argument (0 if invalid number) or default value
*/
- int64_t GetIntArg(const std::string& strArg, int64_t nDefault) const;
- std::optional<int64_t> GetIntArg(const std::string& strArg) const;
+ template <std::integral Int>
+ Int GetArg(const std::string& strArg, Int nDefault) const;
+
+ template <std::integral Int>
+ std::optional<Int> GetArg(const std::string& strArg) const;
+
+ int64_t GetIntArg(const std::string& strArg, int64_t nDefault) const { return GetArg<int64_t>(strArg, nDefault); }
+ std::optional<int64_t> GetIntArg(const std::string& strArg) const { return GetArg<int64_t>(strArg); }
/**
* Return boolean argument or default value
diff --git a/src/test/getarg_tests.cpp b/src/test/getarg_tests.cpp
index ee369272..ec17fe39 100644
--- a/src/test/getarg_tests.cpp
+++ b/src/test/getarg_tests.cpp
@@ -247,26 +247,41 @@ BOOST_AUTO_TEST_CASE(intarg)
const auto foo = std::make_pair("-foo", ArgsManager::ALLOW_ANY);
const auto bar = std::make_pair("-bar", ArgsManager::ALLOW_ANY);
SetupArgs(local_args, {foo, bar});
+
ResetArgs(local_args, "");
+ BOOST_CHECK(!local_args.GetArg<int64_t>("-foo").has_value());
+ BOOST_CHECK(!local_args.GetArg<uint8_t>("-bar").has_value());
BOOST_CHECK_EQUAL(local_args.GetIntArg("-foo", 11), 11);
BOOST_CHECK_EQUAL(local_args.GetIntArg("-foo", 0), 0);
+ BOOST_CHECK_EQUAL(local_args.GetArg("-bar", uint8_t{222}), 222);
+ BOOST_CHECK_EQUAL(local_args.GetArg("-bar", uint8_t{0}), 0);
ResetArgs(local_args, "-foo -bar");
+ BOOST_CHECK_EQUAL(local_args.GetArg<int64_t>("-foo"), 0);
+ BOOST_CHECK_EQUAL(local_args.GetArg<uint8_t>("-bar"), 0);
BOOST_CHECK_EQUAL(local_args.GetIntArg("-foo", 11), 0);
- BOOST_CHECK_EQUAL(local_args.GetIntArg("-bar", 11), 0);
+ BOOST_CHECK_EQUAL(local_args.GetArg("-bar", uint8_t{222}), 0);
// Check under-/overflow behavior.
ResetArgs(local_args, "-foo=-9223372036854775809 -bar=9223372036854775808");
+ BOOST_CHECK_EQUAL(local_args.GetArg<int64_t>("-foo"), std::numeric_limits<int64_t>::min());
+ BOOST_CHECK_EQUAL(local_args.GetArg<uint8_t>("-bar"), std::numeric_limits<uint8_t>::max());
BOOST_CHECK_EQUAL(local_args.GetIntArg("-foo", 0), std::numeric_limits<int64_t>::min());
BOOST_CHECK_EQUAL(local_args.GetIntArg("-bar", 0), std::numeric_limits<int64_t>::max());
+ BOOST_CHECK_EQUAL(local_args.GetArg("-foo", uint8_t{0}), std::numeric_limits<uint8_t>::min());
+ BOOST_CHECK_EQUAL(local_args.GetArg("-bar", uint8_t{0}), std::numeric_limits<uint8_t>::max());
ResetArgs(local_args, "-foo=11 -bar=12");
+ BOOST_CHECK_EQUAL(local_args.GetArg<int64_t>("-foo"), 11);
+ BOOST_CHECK_EQUAL(local_args.GetArg<uint8_t>("-bar"), 12);
BOOST_CHECK_EQUAL(local_args.GetIntArg("-foo", 0), 11);
- BOOST_CHECK_EQUAL(local_args.GetIntArg("-bar", 11), 12);
+ BOOST_CHECK_EQUAL(local_args.GetArg("-bar", uint8_t{11}), 12);
ResetArgs(local_args, "-foo=NaN -bar=NotANumber");
+ BOOST_CHECK_EQUAL(local_args.GetArg<int64_t>("-foo"), 0);
+ BOOST_CHECK_EQUAL(local_args.GetArg<uint8_t>("-bar"), 0);
BOOST_CHECK_EQUAL(local_args.GetIntArg("-foo", 1), 0);
- BOOST_CHECK_EQUAL(local_args.GetIntArg("-bar", 11), 0);
+ BOOST_CHECK_EQUAL(local_args.GetArg("-bar", uint8_t{11}), 0);
}
BOOST_AUTO_TEST_CASE(patharg)
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.