summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Mutz <marc.mutz@kdab.com>2014-09-07 21:11:55 +0200
committerMarc Mutz <marc.mutz@kdab.com>2014-09-12 09:57:16 +0200
commitbb56586e32677ee9be23bffa4f3cc9a913ef192f (patch)
tree2de11368ac0a32a244b943dbf29ad38e8e8c3a43
parent6be26d90517bcbae252689679371cd4c7b7bbe3e (diff)
Add qEnvironmentVariableIntValue()
A lot of code in Qt uses VAR=1 for enabling or disabling some feature or other, ignoring qEnvironmentVariableIsSet(), which was added for that purpose. Other code actually reads numerical values from environment variables. For both use-cases, provide a non-throwing, non-memory-allocating way to get the numerical (int) value of an environment variable, complementing qEnvironmentVariableIs{Set,Empty}(). [ChangeLog][QtCore] Added qEnvironmentVariableIntValue(). Change-Id: I81c85287ea10d355c1bbf8d7807ec9a0e477bce0 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r--src/corelib/global/qglobal.cpp48
-rw-r--r--src/corelib/global/qglobal.h1
-rw-r--r--tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp68
3 files changed, 117 insertions, 0 deletions
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index a0c943df62..f526387eb4 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -47,6 +47,7 @@
#include "qthreadstorage.h"
#include "qdir.h"
#include "qdatetime.h"
+#include <private/qlocale_tools_p.h>
#ifndef QT_NO_QOBJECT
#include <private/qthread_p.h>
@@ -3013,6 +3014,53 @@ bool qEnvironmentVariableIsEmpty(const char *varName) Q_DECL_NOEXCEPT
/*!
\relates <QtGlobal>
+ \since 5.5
+
+ Returns the numerical value of the environment variable \a varName.
+ If \a ok is not null, sets \c{*ok} to \c true or \c false depending
+ on the success of the conversion.
+
+ Equivalent to
+ \code
+ qgetenv(varName).toInt()
+ \endcode
+ except that it's much faster, and can't throw exceptions.
+
+ \sa qgetenv(), qEnvironmentVariableIsSet()
+*/
+int qEnvironmentVariableIntValue(const char *varName, bool *ok) Q_DECL_NOEXCEPT
+{
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+ // we provide a buffer that can hold any int value:
+ static const int NumBinaryDigitsPerOctalDigit = 3;
+ static const int MaxDigitsForOctalInt =
+ (std::numeric_limits<uint>::digits + NumBinaryDigitsPerOctalDigit - 1) / NumBinaryDigitsPerOctalDigit;
+ char buffer[MaxDigitsForOctalInt + 2]; // +1 for NUL +1 for optional '-'
+ size_t dummy;
+ if (getenv_s(&dummy, buffer, sizeof buffer, varName) != 0) {
+ if (ok)
+ *ok = false;
+ return 0;
+ }
+#else
+ const char * const buffer = ::getenv(varName);
+ if (!buffer || !*buffer) {
+ if (ok)
+ *ok = false;
+ return 0;
+ }
+#endif
+ const qlonglong value = qstrtoll(buffer, Q_NULLPTR, 0, ok);
+ if (int(value) != value) { // this is the check in QByteArray::toInt(), keep it in sync
+ if (ok)
+ *ok = false;
+ return 0;
+ }
+ return int(value);
+}
+
+/*!
+ \relates <QtGlobal>
\since 5.1
Returns whether the environment variable \a varName is set.
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index 9176d80f43..412996e462 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -1035,6 +1035,7 @@ Q_CORE_EXPORT bool qunsetenv(const char *varName);
Q_CORE_EXPORT bool qEnvironmentVariableIsEmpty(const char *varName) Q_DECL_NOEXCEPT;
Q_CORE_EXPORT bool qEnvironmentVariableIsSet(const char *varName) Q_DECL_NOEXCEPT;
+Q_CORE_EXPORT int qEnvironmentVariableIntValue(const char *varName, bool *ok=0) Q_DECL_NOEXCEPT;
inline int qIntCast(double f) { return int(f); }
inline int qIntCast(float f) { return int(f); }
diff --git a/tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp b/tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp
index ef41ef8801..e95b86d239 100644
--- a/tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp
+++ b/tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp
@@ -49,14 +49,22 @@ class tst_QGetPutEnv : public QObject
Q_OBJECT
private slots:
void getSetCheck();
+ void intValue_data();
+ void intValue();
};
void tst_QGetPutEnv::getSetCheck()
{
const char varName[] = "should_not_exist";
+ bool ok;
+
QVERIFY(!qEnvironmentVariableIsSet(varName));
QVERIFY(qEnvironmentVariableIsEmpty(varName));
+ ok = true;
+ QCOMPARE(qEnvironmentVariableIntValue(varName), 0);
+ QCOMPARE(qEnvironmentVariableIntValue(varName, &ok), 0);
+ QVERIFY(!ok);
QByteArray result = qgetenv(varName);
QCOMPARE(result, QByteArray());
@@ -65,12 +73,20 @@ void tst_QGetPutEnv::getSetCheck()
QVERIFY(qEnvironmentVariableIsSet(varName));
QVERIFY(qEnvironmentVariableIsEmpty(varName));
+ ok = true;
+ QCOMPARE(qEnvironmentVariableIntValue(varName), 0);
+ QCOMPARE(qEnvironmentVariableIntValue(varName, &ok), 0);
+ QVERIFY(!ok);
#endif
QVERIFY(qputenv(varName, QByteArray("supervalue")));
QVERIFY(qEnvironmentVariableIsSet(varName));
QVERIFY(!qEnvironmentVariableIsEmpty(varName));
+ ok = true;
+ QCOMPARE(qEnvironmentVariableIntValue(varName), 0);
+ QCOMPARE(qEnvironmentVariableIntValue(varName, &ok), 0);
+ QVERIFY(!ok);
result = qgetenv(varName);
QVERIFY(result == "supervalue");
@@ -80,9 +96,61 @@ void tst_QGetPutEnv::getSetCheck()
QVERIFY(qunsetenv(varName));
QVERIFY(!qEnvironmentVariableIsSet(varName));
QVERIFY(qEnvironmentVariableIsEmpty(varName));
+ ok = true;
+ QCOMPARE(qEnvironmentVariableIntValue(varName), 0);
+ QCOMPARE(qEnvironmentVariableIntValue(varName, &ok), 0);
+ QVERIFY(!ok);
result = qgetenv(varName);
QCOMPARE(result, QByteArray());
}
+void tst_QGetPutEnv::intValue_data()
+{
+ QTest::addColumn<QByteArray>("value");
+ QTest::addColumn<int>("expected");
+ QTest::addColumn<bool>("ok");
+
+ // most non-success cases already tested in getSetCheck()
+
+#define ROW(x, i, b) \
+ QTest::newRow(#x) << QByteArray(#x) << (i) << (b)
+ ROW(auto, 0, false);
+ ROW(0, 0, true);
+ ROW(1, 1, true);
+ ROW(010, 8, true);
+ ROW(0x10, 16, true);
+ ROW(-1, -1, true);
+ ROW(-010, -8, true);
+ // ROW(0xffffffff, -1, true); // could be expected, but not how QByteArray::toInt() works
+ ROW(0xffffffff, 0, false);
+ const int bases[] = {10, 8, 16};
+ for (size_t i = 0; i < sizeof bases / sizeof *bases; ++i) {
+ QTest::newRow(qPrintable(QString().sprintf("INT_MAX, base %d", bases[i])))
+ << QByteArray::number(INT_MAX) << INT_MAX << true;
+ QTest::newRow(qPrintable(QString().sprintf("INT_MAX+1, base %d", bases[i])))
+ << QByteArray::number(qlonglong(INT_MAX) + 1) << 0 << false;
+ QTest::newRow(qPrintable(QString().sprintf("INT_MIN, base %d", bases[i])))
+ << QByteArray::number(INT_MIN) << INT_MIN << true;
+ QTest::newRow(qPrintable(QString().sprintf("INT_MIN-1, base %d", bases[i])))
+ << QByteArray::number(qlonglong(INT_MIN) - 1) << 0 << false;
+ };
+}
+
+void tst_QGetPutEnv::intValue()
+{
+ const char varName[] = "should_not_exist";
+
+ QFETCH(QByteArray, value);
+ QFETCH(int, expected);
+ QFETCH(bool, ok);
+
+ bool actualOk = !ok;
+
+ QVERIFY(qputenv(varName, value));
+ QCOMPARE(qEnvironmentVariableIntValue(varName), expected);
+ QCOMPARE(qEnvironmentVariableIntValue(varName, &actualOk), expected);
+ QCOMPARE(actualOk, ok);
+}
+
QTEST_MAIN(tst_QGetPutEnv)
#include "tst_qgetputenv.moc"