summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThiago Macieira <[email protected]>2025-02-10 16:00:49 -0800
committerThiago Macieira <[email protected]>2025-02-14 14:02:02 -0800
commitfd3c05cd073b11482560d5f0c30bd415ff16ba6f (patch)
tree97be5b341a7e02ed0dc3d0a4b3b9da1257edec55
parentb888bc09ce33a91800cb2119a52097897f3d62d1 (diff)
Long live qEnvironmentVariableIntegerValue() returning std::optional
That way, we won't need to pass a bool pointer to distinguish an environment variable containing zero from one that failed to parse. [ChangeLog][QtCore][QtEnvironment] Added qEnvironmentVariableIntegerValue(), which returns std::optional<int>. Fixes: QTBUG-133654 Change-Id: If0d6c3a6f7a080588fa5fffd87b9365f0f8e1089 Reviewed-by: Edward Welbourne <[email protected]>
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_global_qglobal.cpp8
-rw-r--r--src/corelib/global/qtenvironmentvariables.cpp67
-rw-r--r--src/corelib/global/qtenvironmentvariables.h3
-rw-r--r--src/gui/kernel/qhighdpiscaling.cpp12
-rw-r--r--tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp8
5 files changed, 74 insertions, 24 deletions
diff --git a/src/corelib/doc/snippets/code/src_corelib_global_qglobal.cpp b/src/corelib/doc/snippets/code/src_corelib_global_qglobal.cpp
index 393bd5778f1..a981163a6e7 100644
--- a/src/corelib/doc/snippets/code/src_corelib_global_qglobal.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_global_qglobal.cpp
@@ -653,6 +653,14 @@ bool readConfiguration(const QFile &file)
qgetenv(varName).toInt(ok, 0)
//! [to-int]
+//! [int-value_or]
+ qEnvironmentVariableIntegerValue(varName).value_or(0)
+//! [int-value_or]
+
+//! [int-eq0]
+ qEnvironmentVariableIntegerValue(varName) == 0
+//! [int-eq0]
+
//! [is-null]
!qgetenv(varName).isNull()
//! [is-null]
diff --git a/src/corelib/global/qtenvironmentvariables.cpp b/src/corelib/global/qtenvironmentvariables.cpp
index f564a523a57..ae213aa1e39 100644
--- a/src/corelib/global/qtenvironmentvariables.cpp
+++ b/src/corelib/global/qtenvironmentvariables.cpp
@@ -38,7 +38,7 @@ Q_CONSTINIT static QBasicMutex environmentMutex;
On Unix systems, this function is lossless.
\sa qputenv(), qEnvironmentVariable(), qEnvironmentVariableIsSet(),
- qEnvironmentVariableIsEmpty()
+ qEnvironmentVariableIsEmpty(), qEnvironmentVariableIntegerValue()
*/
QByteArray qgetenv(const char *varName)
{
@@ -104,7 +104,8 @@ QByteArray qgetenv(const char *varName)
\note the variable name \a varName must contain only US-ASCII characters.
- \sa qputenv(), qgetenv(), qEnvironmentVariableIsSet(), qEnvironmentVariableIsEmpty()
+ \sa qputenv(), qgetenv(), qEnvironmentVariableIsSet(), qEnvironmentVariableIsEmpty(),
+ qEnvironmentVariableIntegerValue()
*/
QString qEnvironmentVariable(const char *varName, const QString &defaultValue)
{
@@ -193,6 +194,45 @@ bool qEnvironmentVariableIsEmpty(const char *varName) noexcept
*/
int qEnvironmentVariableIntValue(const char *varName, bool *ok) noexcept
{
+ std::optional<int> value = qEnvironmentVariableIntegerValue(varName);
+ if (ok)
+ *ok = bool(value);
+ return value.value_or(0);
+}
+
+/*!
+ \relates <QtEnvironmentVariables>
+ \since 6.10
+
+ Returns the numerical value of the environment variable \a varName. If the
+ variable is not set or could not be parsed as an integer, it returns
+ \c{std::nullopt}.
+
+ Similar to
+ \snippet code/src_corelib_global_qglobal.cpp to-int
+ except that it's much faster, and can't throw exceptions.
+
+ If a value of zero is semantically the same as an empty or unset variable,
+ applications can use
+ \snippet code/src_corelib_global_qglobal.cpp int-value_or
+ Do note in this case that failures to parse a value will also produce a
+ zero.
+
+ But if a value of zero can be used to disable some functionality,
+ applications can compare the returned \c{std::optional} to zero, which will
+ only be true if the variable was set and contained a number that parsed as
+ zero, as in:
+ \snippet code/src_corelib_global_qglobal.cpp int-eq0
+
+ \note there's a limit on the length of the value, which is sufficient for
+ all valid values of int, not counting leading zeroes or spaces. Values that
+ are too long will either be truncated or this function will return
+ \c{std::nullopt}.
+
+ \sa qgetenv(), qEnvironmentVariable(), qEnvironmentVariableIsSet()
+*/
+std::optional<int> qEnvironmentVariableIntegerValue(const char *varName) noexcept
+{
static const int NumBinaryDigitsPerOctalDigit = 3;
static const int MaxDigitsForOctalInt =
(std::numeric_limits<uint>::digits + NumBinaryDigitsPerOctalDigit - 1) / NumBinaryDigitsPerOctalDigit
@@ -205,21 +245,19 @@ int qEnvironmentVariableIntValue(const char *varName, bool *ok) noexcept
// we provide a buffer that can hold any int value:
char buffer[MaxDigitsForOctalInt + 1]; // +1 for the terminating null
size_t dummy;
- if (getenv_s(&dummy, buffer, sizeof buffer, varName) != 0) {
- if (ok)
- *ok = false;
- return 0;
- }
+ if (getenv_s(&dummy, buffer, sizeof buffer, varName) != 0)
+ return std::nullopt;
size = strlen(buffer);
#else
const char * const buffer = ::getenv(varName);
- if (!buffer || (size = strlen(buffer)) > MaxDigitsForOctalInt) {
- if (ok)
- *ok = false;
- return 0;
- }
+ if (!buffer || (size = strlen(buffer)) > MaxDigitsForOctalInt)
+ return std::nullopt;
#endif
- return QByteArrayView(buffer, size).toInt(ok, 0);
+ bool ok;
+ int value = QByteArrayView(buffer, size).toInt(&ok, 0);
+ if (!ok)
+ return std::nullopt;
+ return value;
}
/*!
@@ -232,7 +270,8 @@ int qEnvironmentVariableIntValue(const char *varName, bool *ok) noexcept
\snippet code/src_corelib_global_qglobal.cpp is-null
except that it's potentially much faster, and can't throw exceptions.
- \sa qgetenv(), qEnvironmentVariable(), qEnvironmentVariableIsEmpty()
+ \sa qgetenv(), qEnvironmentVariable(), qEnvironmentVariableIsEmpty(),
+ qEnvironmentVariableIntegerValue()
*/
bool qEnvironmentVariableIsSet(const char *varName) noexcept
{
diff --git a/src/corelib/global/qtenvironmentvariables.h b/src/corelib/global/qtenvironmentvariables.h
index e7be1826779..24658c415e5 100644
--- a/src/corelib/global/qtenvironmentvariables.h
+++ b/src/corelib/global/qtenvironmentvariables.h
@@ -8,6 +8,8 @@
#include <QtCore/qtcoreexports.h>
#include <QtCore/qtdeprecationmarkers.h>
+#include <optional>
+
#if 0
#pragma qt_class(QtEnvironmentVariables)
#pragma qt_sync_stop_processing
@@ -32,6 +34,7 @@ Q_CORE_EXPORT bool qunsetenv(const char *varName);
Q_CORE_EXPORT bool qEnvironmentVariableIsEmpty(const char *varName) noexcept;
Q_CORE_EXPORT bool qEnvironmentVariableIsSet(const char *varName) noexcept;
Q_CORE_EXPORT int qEnvironmentVariableIntValue(const char *varName, bool *ok=nullptr) noexcept;
+Q_CORE_EXPORT std::optional<int> qEnvironmentVariableIntegerValue(const char *varName) noexcept;
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qhighdpiscaling.cpp b/src/gui/kernel/qhighdpiscaling.cpp
index 6fead184c2a..9e38353e419 100644
--- a/src/gui/kernel/qhighdpiscaling.cpp
+++ b/src/gui/kernel/qhighdpiscaling.cpp
@@ -40,14 +40,6 @@ static std::optional<QByteArray> qEnvironmentVariableOptionalByteArray(const cha
return value.isNull() ? std::nullopt : std::optional(std::move(value));
}
-static std::optional<int> qEnvironmentVariableOptionalInt(const char *name)
-{
- bool ok = false;
- const int value = qEnvironmentVariableIntValue(name, &ok);
- auto opt = ok ? std::optional(value) : std::nullopt;
- return opt;
-}
-
static std::optional<qreal> qEnvironmentVariableOptionalReal(const char *name)
{
const QByteArray val = qgetenv(name);
@@ -402,7 +394,7 @@ void QHighDpiScaling::initHighDpiScaling()
// Read environment variables
static const char* envDebugStr = "environment variable set:";
- std::optional<int> envEnableHighDpiScaling = qEnvironmentVariableOptionalInt(enableHighDpiScalingEnvVar);
+ std::optional<int> envEnableHighDpiScaling = qEnvironmentVariableIntegerValue(enableHighDpiScalingEnvVar);
if (envEnableHighDpiScaling.has_value())
qCDebug(lcHighDpi) << envDebugStr << enableHighDpiScalingEnvVar << envEnableHighDpiScaling.value();
@@ -414,7 +406,7 @@ void QHighDpiScaling::initHighDpiScaling()
if (envScreenFactors.has_value())
qCDebug(lcHighDpi) << envDebugStr << screenFactorsEnvVar << envScreenFactors.value();
- std::optional<int> envUsePhysicalDpi = qEnvironmentVariableOptionalInt(usePhysicalDpiEnvVar);
+ std::optional<int> envUsePhysicalDpi = qEnvironmentVariableIntegerValue(usePhysicalDpiEnvVar);
if (envUsePhysicalDpi.has_value())
qCDebug(lcHighDpi) << envDebugStr << usePhysicalDpiEnvVar << envUsePhysicalDpi.value();
diff --git a/tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp b/tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp
index 126fdc8ae6e..01be9463813 100644
--- a/tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp
+++ b/tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp
@@ -28,6 +28,7 @@ void tst_QGetPutEnv::getSetCheck()
QVERIFY(!qEnvironmentVariableIsSet(varName));
QVERIFY(qEnvironmentVariableIsEmpty(varName));
+ QCOMPARE(qEnvironmentVariableIntegerValue(varName), std::nullopt);
ok = true;
QCOMPARE(qEnvironmentVariableIntValue(varName), 0);
QCOMPARE(qEnvironmentVariableIntValue(varName, &ok), 0);
@@ -44,6 +45,7 @@ void tst_QGetPutEnv::getSetCheck()
QVERIFY(qEnvironmentVariableIsSet(varName));
QVERIFY(qEnvironmentVariableIsEmpty(varName));
+ QCOMPARE(qEnvironmentVariableIntegerValue(varName), std::nullopt);
ok = true;
QCOMPARE(qEnvironmentVariableIntValue(varName), 0);
QCOMPARE(qEnvironmentVariableIntValue(varName, &ok), 0);
@@ -68,6 +70,7 @@ void tst_QGetPutEnv::getSetCheck()
QVERIFY(qEnvironmentVariableIsSet(varName));
QVERIFY(!qEnvironmentVariableIsEmpty(varName));
+ QCOMPARE(qEnvironmentVariableIntegerValue(varName), std::nullopt);
ok = true;
QCOMPARE(qEnvironmentVariableIntValue(varName), 0);
QCOMPARE(qEnvironmentVariableIntValue(varName, &ok), 0);
@@ -85,6 +88,7 @@ void tst_QGetPutEnv::getSetCheck()
QVERIFY(qunsetenv(varName));
QVERIFY(!qEnvironmentVariableIsSet(varName)); // note: might fail on some systems!
QVERIFY(qEnvironmentVariableIsEmpty(varName));
+ QCOMPARE(qEnvironmentVariableIntegerValue(varName), std::nullopt);
ok = true;
QCOMPARE(qEnvironmentVariableIntValue(varName), 0);
QCOMPARE(qEnvironmentVariableIntValue(varName, &ok), 0);
@@ -210,6 +214,10 @@ void tst_QGetPutEnv::intValue()
QCOMPARE(qEnvironmentVariableIntValue(varName), expected);
QCOMPARE(qEnvironmentVariableIntValue(varName, &actualOk), expected);
QCOMPARE(actualOk, ok);
+ if (actualOk)
+ QCOMPARE(qEnvironmentVariableIntegerValue(varName), expected);
+ else
+ QCOMPARE(qEnvironmentVariableIntegerValue(varName), std::nullopt);
}
QTEST_MAIN(tst_QGetPutEnv)