diff options
author | Marc Mutz <marc.mutz@qt.io> | 2022-08-03 19:23:28 +0200 |
---|---|---|
committer | Marc Mutz <marc.mutz@qt.io> | 2022-08-06 14:21:46 +0000 |
commit | 5ff71637968c70f138d8ea6cc24e61c1608f2187 (patch) | |
tree | 4b4f605969497961e70ad311b2ebed3d0b4060e3 /src | |
parent | 5b62970b9441717670a1756b858c500004dfdfe0 (diff) |
qputenv: port to QByteArrayView
The vast majority of in-tree users pass simple and short C string
literals as the value. By porting to QByteArrayView, we document that
we'll accept non-NUL-terminated data, and do the NUL-termination
internally, using SSO'ed std::string, saving memory allocations in the
common case of short strings.
I didn't bother to check which direction std::string takes for
nullptrs these days (there was a change accepted in that area for
C++20 or 23), so play it safe and protect against them.
Follow-up to
Task-number: QTBUG-105302
Change-Id: I2369acc62f1d5cbc26135396cfe0602d8c75300c
Reviewed-by: Sona Kurazyan <sona.kurazyan@qt.io>
Reviewed-by: MÃ¥rten Nordheim <marten.nordheim@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Diffstat (limited to 'src')
-rw-r--r-- | src/corelib/compat/removed_api.cpp | 7 | ||||
-rw-r--r-- | src/corelib/global/qenvironmentvariables.cpp | 25 | ||||
-rw-r--r-- | src/corelib/global/qenvironmentvariables.h | 6 | ||||
-rw-r--r-- | src/gui/opengl/platform/unix/qglxconvenience.cpp | 2 |
4 files changed, 27 insertions, 13 deletions
diff --git a/src/corelib/compat/removed_api.cpp b/src/corelib/compat/removed_api.cpp index 2b864ad41f..aa1a496f0f 100644 --- a/src/corelib/compat/removed_api.cpp +++ b/src/corelib/compat/removed_api.cpp @@ -285,6 +285,13 @@ QT_WARNING_POP #if QT_CORE_REMOVED_SINCE(6, 5) +#include "qenvironmentvariables.h" + +bool qputenv(const char *varName, const QByteArray &value) +{ + return qputenv(varName, qToByteArrayViewIgnoringNull(value)); +} + #include "qmetatype.h" int QMetaType::idHelper() const diff --git a/src/corelib/global/qenvironmentvariables.cpp b/src/corelib/global/qenvironmentvariables.cpp index d3d963e52e..4860913327 100644 --- a/src/corelib/global/qenvironmentvariables.cpp +++ b/src/corelib/global/qenvironmentvariables.cpp @@ -243,6 +243,7 @@ bool qEnvironmentVariableIsSet(const char *varName) noexcept } /*! + \fn bool qputenv(const char *varName, QByteArrayView value) \relates <QEnvironmentVariables> This function sets the \a value of the environment variable named @@ -258,30 +259,30 @@ bool qEnvironmentVariableIsSet(const char *varName) noexcept uses the replacement function in VC, and calls the standard C library's implementation on all other platforms. + \note In Qt versions prior to 6.5, the \a value argument was QByteArray, + not QByteArrayView. + \sa qgetenv(), qEnvironmentVariable() */ -bool qputenv(const char *varName, const QByteArray &value) +bool qputenv(const char *varName, QByteArrayView raw) { - // protect against non-NUL-terminated QByteArrays: - if (!const_cast<QByteArray&>(value).data_ptr()->isMutable()) { - QByteArray copy(value); - copy.reserve(copy.size() + 1); // ensures NUL termination (and isMutable() even for size==0 - // (unlike detach()) to avoid infinite recursion) - return qputenv(varName, copy); - } + auto protect = [](const char *str) { return str ? str : ""; }; + + std::string value{protect(raw.data()), size_t(raw.size())}; // NUL-terminates w/SSO #if defined(Q_CC_MSVC) const auto locker = qt_scoped_lock(environmentMutex); - return _putenv_s(varName, value.constData()) == 0; + return _putenv_s(varName, value.data()) == 0; #elif (defined(_POSIX_VERSION) && (_POSIX_VERSION-0) >= 200112L) || defined(Q_OS_HAIKU) // POSIX.1-2001 has setenv const auto locker = qt_scoped_lock(environmentMutex); - return setenv(varName, value.constData(), true) == 0; + return setenv(varName, value.data(), true) == 0; #else - QByteArray buffer(varName); + std::string buffer; + buffer += protect(varName); buffer += '='; buffer += value; - char *envVar = qstrdup(buffer.constData()); + char *envVar = qstrdup(buffer.data()); int result = [&] { const auto locker = qt_scoped_lock(environmentMutex); return putenv(envVar); diff --git a/src/corelib/global/qenvironmentvariables.h b/src/corelib/global/qenvironmentvariables.h index cde51c9ba1..78fea255d3 100644 --- a/src/corelib/global/qenvironmentvariables.h +++ b/src/corelib/global/qenvironmentvariables.h @@ -5,6 +5,7 @@ #define QENVIRONMENTVARIABLES_H #include <QtCore/qglobal.h> +#include <QtCore/qtdeprecationmarkers.h> #if 0 #pragma qt_class(QEnvironmentVariables) @@ -14,11 +15,16 @@ QT_BEGIN_NAMESPACE class QByteArray; +class QByteArrayView; + Q_CORE_EXPORT QByteArray qgetenv(const char *varName); // need it as two functions because QString is only forward-declared here Q_CORE_EXPORT QString qEnvironmentVariable(const char *varName); Q_CORE_EXPORT QString qEnvironmentVariable(const char *varName, const QString &defaultValue); +#if QT_CORE_REMOVED_SINCE(6, 5) Q_CORE_EXPORT bool qputenv(const char *varName, const QByteArray &value); +#endif +Q_CORE_EXPORT bool qputenv(const char *varName, QByteArrayView value); Q_CORE_EXPORT bool qunsetenv(const char *varName); Q_CORE_EXPORT bool qEnvironmentVariableIsEmpty(const char *varName) noexcept; diff --git a/src/gui/opengl/platform/unix/qglxconvenience.cpp b/src/gui/opengl/platform/unix/qglxconvenience.cpp index a756caf343..ce70818042 100644 --- a/src/gui/opengl/platform/unix/qglxconvenience.cpp +++ b/src/gui/opengl/platform/unix/qglxconvenience.cpp @@ -124,7 +124,7 @@ struct QXcbSoftwareOpenGLEnforcer { } if (forceSoftwareOpenGL) - qputenv("LIBGL_ALWAYS_SOFTWARE", QByteArrayLiteral("1")); + qputenv("LIBGL_ALWAYS_SOFTWARE", "1"); } ~QXcbSoftwareOpenGLEnforcer() { |