diff options
Diffstat (limited to 'src/corelib/global/qglobal.cpp')
-rw-r--r-- | src/corelib/global/qglobal.cpp | 665 |
1 files changed, 344 insertions, 321 deletions
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index ea2c8d3ae2..2d8b860c5b 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2016 Intel Corporation. +** Copyright (C) 2017 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -42,7 +42,6 @@ #include "qstring.h" #include "qvector.h" #include "qlist.h" -#include "qthreadstorage.h" #include "qdir.h" #include "qdatetime.h" #include "qoperatingsystemversion.h" @@ -77,6 +76,10 @@ #include <Ws2tcpip.h> #endif // Q_OS_WINRT +#ifdef Q_OS_WIN +# include <qt_windows.h> +#endif + #if defined(Q_OS_VXWORKS) && defined(_WRS_KERNEL) # include <envLib.h> #endif @@ -134,6 +137,38 @@ Q_CORE_EXPORT void *qMemSet(void *dest, int c, size_t n); Q_STATIC_ASSERT_X(sizeof(int) == 4, "Qt assumes that int is 32 bits"); Q_STATIC_ASSERT_X(UCHAR_MAX == 255, "Qt assumes that char is 8 bits"); Q_STATIC_ASSERT_X(QT_POINTER_SIZE == sizeof(void *), "QT_POINTER_SIZE defined incorrectly"); +Q_STATIC_ASSERT_X(sizeof(float) == 4, "Qt assumes that float is 32 bits"); + +// While we'd like to check for __STDC_IEC_559__, as per ISO/IEC 9899:2011 +// Annex F (C11, normative for C++11), there are a few corner cases regarding +// denormals where GHS compiler is relying hardware behavior that is not IEC +// 559 compliant. So split the check in several subchecks. + +// On GHC the compiler reports std::numeric_limits<float>::is_iec559 as false. +// This is all right according to our needs. +#if !defined(Q_CC_GHS) +Q_STATIC_ASSERT_X(std::numeric_limits<float>::is_iec559, + "Qt assumes IEEE 754 floating point"); +#endif + +// Technically, presence of NaN and infinities are implied from the above check, +// but double checking our environment doesn't hurt... +Q_STATIC_ASSERT_X(std::numeric_limits<float>::has_infinity && + std::numeric_limits<float>::has_quiet_NaN && + std::numeric_limits<float>::has_signaling_NaN, + "Qt assumes IEEE 754 floating point"); + +// is_iec559 checks for ISO/IEC/IEEE 60559:2011 (aka IEEE 754-2008) compliance, +// but that allows for a non-binary radix. We need to recheck that. +// Note how __STDC_IEC_559__ would instead check for IEC 60559:1989, aka +// ANSI/IEEE 754−1985, which specifically implies binary floating point numbers. +Q_STATIC_ASSERT_X(std::numeric_limits<float>::radix == 2, + "Qt assumes binary IEEE 754 floating point"); + +// not required by the definition of size_t, but we depend on this +Q_STATIC_ASSERT_X(sizeof(size_t) == sizeof(void *), "size_t and a pointer don't have the same size"); +Q_STATIC_ASSERT(sizeof(size_t) == sizeof(qsizetype)); // implied by the definition +Q_STATIC_ASSERT((std::is_same<qsizetype, qptrdiff>::value)); /*! \class QFlag @@ -150,28 +185,28 @@ Q_STATIC_ASSERT_X(QT_POINTER_SIZE == sizeof(void *), "QT_POINTER_SIZE defined in /*! \fn QFlag::QFlag(int value) - Constructs a QFlag object that stores the given \a value. + Constructs a QFlag object that stores the \a value. */ /*! \fn QFlag::QFlag(uint value) \since 5.3 - Constructs a QFlag object that stores the given \a value. + Constructs a QFlag object that stores the \a value. */ /*! \fn QFlag::QFlag(short value) \since 5.3 - Constructs a QFlag object that stores the given \a value. + Constructs a QFlag object that stores the \a value. */ /*! \fn QFlag::QFlag(ushort value) \since 5.3 - Constructs a QFlag object that stores the given \a value. + Constructs a QFlag object that stores the \a value. */ /*! @@ -266,29 +301,28 @@ Q_STATIC_ASSERT_X(QT_POINTER_SIZE == sizeof(void *), "QT_POINTER_SIZE defined in */ /*! - \fn QFlags::QFlags(const QFlags &other) + \fn template<typename Enum> QFlags<Enum>::QFlags(const QFlags &other) Constructs a copy of \a other. */ /*! - \fn QFlags::QFlags(Enum flag) + \fn template <typename Enum> QFlags<Enum>::QFlags(Enum flags) - Constructs a QFlags object storing the given \a flag. + Constructs a QFlags object storing the \a flags. */ /*! - \fn QFlags::QFlags(Zero zero) + \fn template <typename Enum> QFlags<Enum>::QFlags(Zero) - Constructs a QFlags object with no flags set. \a zero must be a + Constructs a QFlags object with no flags set. The parameter must be a literal 0 value. */ /*! - \fn QFlags::QFlags(QFlag value) + \fn template <typename Enum> QFlags<Enum>::QFlags(QFlag flag) - Constructs a QFlags object initialized with the given integer \a - value. + Constructs a QFlags object initialized with the integer \a flag. The QFlag type is a helper type. By using it here instead of \c int, we effectively ensure that arbitrary enum values cannot be @@ -297,7 +331,7 @@ Q_STATIC_ASSERT_X(QT_POINTER_SIZE == sizeof(void *), "QT_POINTER_SIZE defined in */ /*! - \fn QFlags::QFlags(std::initializer_list<Enum> flags) + \fn template <typename Enum> QFlags<Enum>::QFlags(std::initializer_list<Enum> flags) \since 5.4 Constructs a QFlags object initialized with all \a flags @@ -307,14 +341,14 @@ Q_STATIC_ASSERT_X(QT_POINTER_SIZE == sizeof(void *), "QT_POINTER_SIZE defined in */ /*! - \fn QFlags &QFlags::operator=(const QFlags &other) + \fn template <typename Enum> QFlags &QFlags<Enum>::operator=(const QFlags &other) Assigns \a other to this object and returns a reference to this object. */ /*! - \fn QFlags &QFlags::operator&=(int mask) + \fn template <typename Enum> QFlags &QFlags<Enum>::operator&=(int mask) Performs a bitwise AND operation with \a mask and stores the result in this QFlags object. Returns a reference to this object. @@ -323,19 +357,19 @@ Q_STATIC_ASSERT_X(QT_POINTER_SIZE == sizeof(void *), "QT_POINTER_SIZE defined in */ /*! - \fn QFlags &QFlags::operator&=(uint mask) + \fn template <typename Enum> QFlags &QFlags<Enum>::operator&=(uint mask) \overload */ /*! - \fn QFlags &QFlags::operator&=(Enum mask) + \fn template <typename Enum> QFlags &QFlags<Enum>::operator&=(Enum mask) \overload */ /*! - \fn QFlags &QFlags::operator|=(QFlags other) + \fn template <typename Enum> QFlags &QFlags<Enum>::operator|=(QFlags other) Performs a bitwise OR operation with \a other and stores the result in this QFlags object. Returns a reference to this object. @@ -344,13 +378,13 @@ Q_STATIC_ASSERT_X(QT_POINTER_SIZE == sizeof(void *), "QT_POINTER_SIZE defined in */ /*! - \fn QFlags &QFlags::operator|=(Enum other) + \fn template <typename Enum> QFlags &QFlags<Enum>::operator|=(Enum other) \overload */ /*! - \fn QFlags &QFlags::operator^=(QFlags other) + \fn template <typename Enum> QFlags &QFlags<Enum>::operator^=(QFlags other) Performs a bitwise XOR operation with \a other and stores the result in this QFlags object. Returns a reference to this object. @@ -359,13 +393,13 @@ Q_STATIC_ASSERT_X(QT_POINTER_SIZE == sizeof(void *), "QT_POINTER_SIZE defined in */ /*! - \fn QFlags &QFlags::operator^=(Enum other) + \fn template <typename Enum> QFlags &QFlags<Enum>::operator^=(Enum other) \overload */ /*! - \fn QFlags::operator Int() const + \fn template <typename Enum> QFlags<Enum>::operator Int() const Returns the value stored in the QFlags object as an integer. @@ -373,7 +407,7 @@ Q_STATIC_ASSERT_X(QT_POINTER_SIZE == sizeof(void *), "QT_POINTER_SIZE defined in */ /*! - \fn QFlags QFlags::operator|(QFlags other) const + \fn template <typename Enum> QFlags QFlags<Enum>::operator|(QFlags other) const Returns a QFlags object containing the result of the bitwise OR operation on this object and \a other. @@ -382,13 +416,13 @@ Q_STATIC_ASSERT_X(QT_POINTER_SIZE == sizeof(void *), "QT_POINTER_SIZE defined in */ /*! - \fn QFlags QFlags::operator|(Enum other) const + \fn template <typename Enum> QFlags QFlags<Enum>::operator|(Enum other) const \overload */ /*! - \fn QFlags QFlags::operator^(QFlags other) const + \fn template <typename Enum> QFlags QFlags<Enum>::operator^(QFlags other) const Returns a QFlags object containing the result of the bitwise XOR operation on this object and \a other. @@ -397,13 +431,13 @@ Q_STATIC_ASSERT_X(QT_POINTER_SIZE == sizeof(void *), "QT_POINTER_SIZE defined in */ /*! - \fn QFlags QFlags::operator^(Enum other) const + \fn template <typename Enum> QFlags QFlags<Enum>::operator^(Enum other) const \overload */ /*! - \fn QFlags QFlags::operator&(int mask) const + \fn template <typename Enum> QFlags QFlags<Enum>::operator&(int mask) const Returns a QFlags object containing the result of the bitwise AND operation on this object and \a mask. @@ -412,19 +446,19 @@ Q_STATIC_ASSERT_X(QT_POINTER_SIZE == sizeof(void *), "QT_POINTER_SIZE defined in */ /*! - \fn QFlags QFlags::operator&(uint mask) const + \fn template <typename Enum> QFlags QFlags<Enum>::operator&(uint mask) const \overload */ /*! - \fn QFlags QFlags::operator&(Enum mask) const + \fn template <typename Enum> QFlags QFlags<Enum>::operator&(Enum mask) const \overload */ /*! - \fn QFlags QFlags::operator~() const + \fn template <typename Enum> QFlags QFlags<Enum>::operator~() const Returns a QFlags object that contains the bitwise negation of this object. @@ -433,24 +467,24 @@ Q_STATIC_ASSERT_X(QT_POINTER_SIZE == sizeof(void *), "QT_POINTER_SIZE defined in */ /*! - \fn bool QFlags::operator!() const + \fn template <typename Enum> bool QFlags<Enum>::operator!() const Returns \c true if no flag is set (i.e., if the value stored by the QFlags object is 0); otherwise returns \c false. */ /*! - \fn bool QFlags::testFlag(Enum flag) const + \fn template <typename Enum> bool QFlags<Enum>::testFlag(Enum flag) const \since 4.2 - Returns \c true if the \a flag is set, otherwise \c false. + Returns \c true if the flag \a flag is set, otherwise \c false. */ /*! - \fn QFlags QFlags::setFlag(Enum flag, bool on) + \fn template <typename Enum> QFlags QFlags<Enum>::setFlag(Enum flag, bool on) \since 5.7 - Sets the indicated \a flag if \a on is \c true or unsets it if + Sets the flag \a flag if \a on is \c true or unsets it if \a on is \c false. Returns a reference to this object. */ @@ -796,6 +830,21 @@ Q_STATIC_ASSERT_X(QT_POINTER_SIZE == sizeof(void *), "QT_POINTER_SIZE defined in */ /*! + \typedef qsizetype + \relates <QtGlobal> + \since 5.10 + + Integral type providing Posix' \c ssize_t for all platforms. + + This type is guaranteed to be the same size as a \c size_t on all + platforms supported by Qt. + + Note that qsizetype is signed. Use \c size_t for unsigned values. + + \sa qptrdiff +*/ + +/*! \enum QtMsgType \relates <QtGlobal> @@ -873,11 +922,11 @@ Q_STATIC_ASSERT_X(QT_POINTER_SIZE == sizeof(void *), "QT_POINTER_SIZE defined in \sa quint64, qlonglong */ -/*! \fn T qAbs(const T &value) +/*! \fn template <typename T> T qAbs(const T &t) \relates <QtGlobal> - Compares \a value to the 0 of type T and returns the absolute - value. Thus if T is \e {double}, then \a value is compared to + Compares \a t to the 0 of type T and returns the absolute + value. Thus if T is \e {double}, then \a t is compared to \e{(double) 0}. Example: @@ -885,50 +934,50 @@ Q_STATIC_ASSERT_X(QT_POINTER_SIZE == sizeof(void *), "QT_POINTER_SIZE defined in \snippet code/src_corelib_global_qglobal.cpp 10 */ -/*! \fn int qRound(double value) +/*! \fn int qRound(double d) \relates <QtGlobal> - Rounds \a value to the nearest integer. + Rounds \a d to the nearest integer. Example: \snippet code/src_corelib_global_qglobal.cpp 11A */ -/*! \fn int qRound(float value) +/*! \fn int qRound(float d) \relates <QtGlobal> - Rounds \a value to the nearest integer. + Rounds \a d to the nearest integer. Example: \snippet code/src_corelib_global_qglobal.cpp 11B */ -/*! \fn qint64 qRound64(double value) +/*! \fn qint64 qRound64(double d) \relates <QtGlobal> - Rounds \a value to the nearest 64-bit integer. + Rounds \a d to the nearest 64-bit integer. Example: \snippet code/src_corelib_global_qglobal.cpp 12A */ -/*! \fn qint64 qRound64(float value) +/*! \fn qint64 qRound64(float d) \relates <QtGlobal> - Rounds \a value to the nearest 64-bit integer. + Rounds \a d to the nearest 64-bit integer. Example: \snippet code/src_corelib_global_qglobal.cpp 12B */ -/*! \fn const T &qMin(const T &value1, const T &value2) +/*! \fn template <typename T> const T &qMin(const T &a, const T &b) \relates <QtGlobal> - Returns the minimum of \a value1 and \a value2. + Returns the minimum of \a a and \a b. Example: @@ -937,10 +986,10 @@ Q_STATIC_ASSERT_X(QT_POINTER_SIZE == sizeof(void *), "QT_POINTER_SIZE defined in \sa qMax(), qBound() */ -/*! \fn const T &qMax(const T &value1, const T &value2) +/*! \fn template <typename T> const T &qMax(const T &a, const T &b) \relates <QtGlobal> - Returns the maximum of \a value1 and \a value2. + Returns the maximum of \a a and \a b. Example: @@ -949,11 +998,11 @@ Q_STATIC_ASSERT_X(QT_POINTER_SIZE == sizeof(void *), "QT_POINTER_SIZE defined in \sa qMin(), qBound() */ -/*! \fn const T &qBound(const T &min, const T &value, const T &max) +/*! \fn template <typename T> const T &qBound(const T &min, const T &val, const T &max) \relates <QtGlobal> - Returns \a value bounded by \a min and \a max. This is equivalent - to qMax(\a min, qMin(\a value, \a max)). + Returns \a val bounded by \a min and \a max. This is equivalent + to qMax(\a min, qMin(\a val, \a max)). Example: @@ -962,7 +1011,7 @@ Q_STATIC_ASSERT_X(QT_POINTER_SIZE == sizeof(void *), "QT_POINTER_SIZE defined in \sa qMin(), qMax() */ -/*! \fn auto qOverload(T functionPointer) +/*! \fn template <typename T> auto qOverload(T functionPointer) \relates <QtGlobal> \since 5.7 @@ -984,7 +1033,7 @@ Q_STATIC_ASSERT_X(QT_POINTER_SIZE == sizeof(void *), "QT_POINTER_SIZE defined in and Functor-Based Connections} */ -/*! \fn auto qConstOverload(T memberFunctionPointer) +/*! \fn template <typename T> auto qConstOverload(T memberFunctionPointer) \relates <QtGlobal> \since 5.7 @@ -996,7 +1045,7 @@ Q_STATIC_ASSERT_X(QT_POINTER_SIZE == sizeof(void *), "QT_POINTER_SIZE defined in and Functor-Based Connections} */ -/*! \fn auto qNonConstOverload(T memberFunctionPointer) +/*! \fn template <typename T> auto qNonConstOverload(T memberFunctionPointer) \relates <QtGlobal> \since 5.7 @@ -1385,13 +1434,6 @@ bool qSharedBuild() Q_DECL_NOTHROW */ /*! - \macro Q_OS_ULTRIX - \relates <QtGlobal> - - Defined on DEC Ultrix. -*/ - -/*! \macro Q_OS_LINUX \relates <QtGlobal> @@ -1427,41 +1469,6 @@ bool qSharedBuild() Q_DECL_NOTHROW */ /*! - \macro Q_OS_BSDI - \relates <QtGlobal> - - Defined on BSD/OS. -*/ - -/*! - \macro Q_OS_IRIX - \relates <QtGlobal> - - Defined on SGI Irix. -*/ - -/*! - \macro Q_OS_OSF - \relates <QtGlobal> - - Defined on HP Tru64 UNIX. -*/ - -/*! - \macro Q_OS_SCO - \relates <QtGlobal> - - Defined on SCO OpenServer 5. -*/ - -/*! - \macro Q_OS_UNIXWARE - \relates <QtGlobal> - - Defined on UnixWare 7, Open UNIX 8. -*/ - -/*! \macro Q_OS_AIX \relates <QtGlobal> @@ -1476,27 +1483,6 @@ bool qSharedBuild() Q_DECL_NOTHROW */ /*! - \macro Q_OS_DGUX - \relates <QtGlobal> - - Defined on DG/UX. -*/ - -/*! - \macro Q_OS_RELIANT - \relates <QtGlobal> - - Defined on Reliant UNIX. -*/ - -/*! - \macro Q_OS_DYNIX - \relates <QtGlobal> - - Defined on DYNIX/ptx. -*/ - -/*! \macro Q_OS_QNX \relates <QtGlobal> @@ -2838,10 +2824,11 @@ QString QSysInfo::prettyProductName() This function returns the same as QHostInfo::localHostName(). - \sa QHostInfo::localDomainName + \sa QHostInfo::localDomainName, machineUniqueId() */ QString QSysInfo::machineHostName() { + // the hostname can change, so we can't cache it #if defined(Q_OS_LINUX) // gethostname(3) on Linux just calls uname(2), so do it ourselves // and avoid a memcpy @@ -2864,6 +2851,119 @@ QString QSysInfo::machineHostName() } #endif // QT_BOOTSTRAPPED +enum { + UuidStringLen = sizeof("00000000-0000-0000-0000-000000000000") - 1 +}; + +/*! + \since 5.10 + + Returns a unique ID for this machine, if one can be determined. If no + unique ID could be determined, this function returns an empty byte array. + Unlike machineHostName(), the value returned by this function is likely + globally unique. + + A unique ID is useful in network operations to identify this machine for an + extended period of time, when the IP address could change or if this + machine could have more than one IP address. For example, the ID could be + used when communicating with a server or when storing device-specific data + in shared network storage. + + Note that on some systems, this value will persist across reboots and on + some it will not. Applications should not blindly depend on this fact + without verifying the OS capabilities. In particular, on Linux systems, + this ID is usually permanent and it matches the D-Bus machine ID, except + for nodes without their own storage (replicated nodes). + + \sa machineHostName(), bootUniqueId() +*/ +QByteArray QSysInfo::machineUniqueId() +{ +#ifdef Q_OS_BSD4 + char uuid[UuidStringLen]; + size_t uuidlen = sizeof(uuid); +# ifdef KERN_HOSTUUID + int name[] = { CTL_KERN, KERN_HOSTUUID }; + if (sysctl(name, sizeof name / sizeof name[0], &uuid, &uuidlen, nullptr, 0) == 0 + && uuidlen == sizeof(uuid)) + return QByteArray(uuid, uuidlen); + +# else + // Darwin: no fixed value, we need to search by name + if (sysctlbyname("kern.uuid", uuid, &uuidlen, nullptr, 0) == 0 && uuidlen == sizeof(uuid)) + return QByteArray(uuid, uuidlen); +# endif +#elif defined(Q_OS_UNIX) + // The modern name on Linux is /etc/machine-id, but that path is + // unlikely to exist on non-Linux (non-systemd) systems. The old + // path is more than enough. + static const char fullfilename[] = "/usr/local/var/lib/dbus/machine-id"; + const char *firstfilename = fullfilename + sizeof("/usr/local") - 1; + int fd = qt_safe_open(firstfilename, O_RDONLY); + if (fd == -1 && errno == ENOENT) + fd = qt_safe_open(fullfilename, O_RDONLY); + + if (fd != -1) { + char buffer[32]; // 128 bits, hex-encoded + qint64 len = qt_safe_read(fd, buffer, sizeof(buffer)); + qt_safe_close(fd); + + if (len != -1) + return QByteArray(buffer, len); + } +#elif defined(Q_OS_WIN) && !defined(Q_OS_WINRT) + // Let's poke at the registry + HKEY key = NULL; + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Cryptography", 0, KEY_READ, &key) + == ERROR_SUCCESS) { + wchar_t buffer[UuidStringLen + 1]; + DWORD size = sizeof(buffer); + bool ok = (RegQueryValueEx(key, L"MachineGuid", NULL, NULL, (LPBYTE)buffer, &size) == + ERROR_SUCCESS); + RegCloseKey(key); + if (ok) + return QStringView(buffer, (size - 1) / 2).toLatin1(); + } +#endif + return QByteArray(); +} + +/*! + \since 5.10 + + Returns a unique ID for this machine's boot, if one can be determined. If + no unique ID could be determined, this function returns an empty byte + array. This value is expected to change after every boot and can be + considered globally unique. + + This function is currently only implemented for Linux and Apple operating + systems. + + \sa machineUniqueId() +*/ +QByteArray QSysInfo::bootUniqueId() +{ +#ifdef Q_OS_LINUX + // use low-level API here for simplicity + int fd = qt_safe_open("/proc/sys/kernel/random/boot_id", O_RDONLY); + if (fd != -1) { + char uuid[UuidStringLen]; + qint64 len = qt_safe_read(fd, uuid, sizeof(uuid)); + qt_safe_close(fd); + if (len == UuidStringLen) + return QByteArray(uuid, UuidStringLen); + } +#elif defined(Q_OS_DARWIN) + // "kern.bootsessionuuid" is only available by name + char uuid[UuidStringLen]; + size_t uuidlen = sizeof(uuid); + if (sysctlbyname("kern.bootsessionuuid", uuid, &uuidlen, nullptr, 0) == 0 + && uuidlen == sizeof(uuid)) + return QByteArray(uuid, uuidlen); +#endif + return QByteArray(); +}; + /*! \macro void Q_ASSERT(bool test) \relates <QtGlobal> @@ -3007,10 +3107,10 @@ QString QSysInfo::machineHostName() */ /*! - \fn T *q_check_ptr(T *pointer) + \fn template <typename T> T *q_check_ptr(T *p) \relates <QtGlobal> - Uses Q_CHECK_PTR on \a pointer, then returns \a pointer. + Uses Q_CHECK_PTR on \a p, then returns \a p. This can be used as an inline version of Q_CHECK_PTR. */ @@ -3094,7 +3194,7 @@ void qt_assert_x(const char *where, const char *what, const char *file, int line Deliberately not exported as part of the Qt API, but used in both qsimplerichtext.cpp and qgfxraster_qws.cpp */ -Q_CORE_EXPORT unsigned int qt_int_sqrt(unsigned int n) +Q_CORE_EXPORT Q_DECL_CONST_FUNCTION unsigned int qt_int_sqrt(unsigned int n) { // n must be in the range 0...UINT_MAX/2-1 if (n >= (UINT_MAX>>2)) { @@ -3124,29 +3224,32 @@ void *qMemSet(void *dest, int c, size_t n) { return memset(dest, c, n); } // add thread-safety for the Qt wrappers. static QBasicMutex environmentMutex; -// getenv is declared as deprecated in VS2005. This function -// makes use of the new secure getenv function. /*! \relates <QtGlobal> + \threadsafe - Returns the value of the environment variable with name \a - varName. To get the variable string, use QByteArray::constData(). - To convert the data to a QString use QString::fromLocal8Bit(). + Returns the value of the environment variable with name \a varName as a + QByteArray. If no variable by that name is found in the environment, this + function returns a default-constructed QByteArray. - \note qgetenv() was introduced because getenv() from the standard - C library was deprecated in VC2005 (and later versions). qgetenv() - uses the new replacement function in VC, and calls the standard C - library's implementation on all other platforms. + The Qt environment manipulation functions are thread-safe, but this + requires that the C library equivalent functions like getenv and putenv are + not directly called. + + To convert the data to a QString use QString::fromLocal8Bit(). - \warning Don't use qgetenv on Windows if the content may contain - non-US-ASCII characters, like file paths. + \note on desktop Windows, qgetenv() may produce data loss if the + original string contains Unicode characters not representable in the + ANSI encoding. Use qEnvironmentVariable() instead. + On Unix systems, this function is lossless. - \sa qputenv(), qEnvironmentVariableIsSet(), qEnvironmentVariableIsEmpty() + \sa qputenv(), qEnvironmentVariable(), qEnvironmentVariableIsSet(), + qEnvironmentVariableIsEmpty() */ QByteArray qgetenv(const char *varName) { QMutexLocker locker(&environmentMutex); -#if defined(_MSC_VER) && _MSC_VER >= 1400 +#ifdef Q_CC_MSVC size_t requiredSize = 0; QByteArray buffer; getenv_s(&requiredSize, 0, 0, varName); @@ -3163,6 +3266,92 @@ QByteArray qgetenv(const char *varName) #endif } + +/*! + QString qEnvironmentVariable(const char *varName, const QString &defaultValue); + + \relates <QtGlobal> + \since 5.10 + + Returns the value of the environment variable with name \a varName as a + QString. If no variable by that name is found in the environment, this + function returns \a defaultValue. + + The Qt environment manipulation functions are thread-safe, but this + requires that the C library equivalent functions like getenv and putenv are + not directly called. + + The following table describes how to choose between qgetenv() and + qEnvironmentVariable(): + \table + \header \li Condition \li Recommendation + \row + \li Variable contains file paths or user text + \li qEnvironmentVariable() + \row + \li Windows-specific code + \li qEnvironmentVariable() + \row + \li Unix-specific code, destination variable is not QString and/or is + used to interface with non-Qt APIs + \li qgetenv() + \row + \li Destination variable is a QString + \li qEnvironmentVariable() + \row + \li Destination variable is a QByteArray or std::string + \li qgetenv() + \endtable + + \note on Unix systems, this function may produce data loss if the original + string contains arbitrary binary data that cannot be decoded by the locale + codec. Use qgetenv() instead for that case. On Windows, this function is + lossless. + + \note the variable name \a varName must contain only US-ASCII characters. + + \sa qputenv(), qgetenv(), qEnvironmentVariableIsSet(), qEnvironmentVariableIsEmpty() +*/ +QString qEnvironmentVariable(const char *varName, const QString &defaultValue) +{ +#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) + QMutexLocker locker(&environmentMutex); + QVarLengthArray<wchar_t, 32> wname(int(strlen(varName)) + 1); + for (int i = 0; i < wname.size(); ++i) // wname.size() is correct: will copy terminating null + wname[i] = uchar(varName[i]); + size_t requiredSize = 0; + QString buffer; + _wgetenv_s(&requiredSize, 0, 0, wname.data()); + if (requiredSize == 0) + return defaultValue; + buffer.resize(int(requiredSize)); + _wgetenv_s(&requiredSize, reinterpret_cast<wchar_t *>(buffer.data()), requiredSize, + wname.data()); + // requiredSize includes the terminating null, which we don't want. + Q_ASSERT(buffer.endsWith(QLatin1Char('\0'))); + buffer.chop(1); + return buffer; +#else + QByteArray value = qgetenv(varName); + if (value.isNull()) + return defaultValue; +// duplicated in qfile.h (QFile::decodeName) +#if defined(Q_OS_DARWIN) + return QString::fromUtf8(value).normalized(QString::NormalizationForm_C); +#else // other Unix + return QString::fromLocal8Bit(value); +#endif +#endif +} + +/*! + \internal +*/ +QString qEnvironmentVariable(const char *varName) +{ + return qEnvironmentVariable(varName, QString()); +} + /*! \relates <QtGlobal> \since 5.1 @@ -3175,12 +3364,12 @@ QByteArray qgetenv(const char *varName) \endcode except that it's potentially much faster, and can't throw exceptions. - \sa qgetenv(), qEnvironmentVariableIsSet() + \sa qgetenv(), qEnvironmentVariable(), qEnvironmentVariableIsSet() */ bool qEnvironmentVariableIsEmpty(const char *varName) Q_DECL_NOEXCEPT { QMutexLocker locker(&environmentMutex); -#if defined(_MSC_VER) && _MSC_VER >= 1400 +#ifdef Q_CC_MSVC // we provide a buffer that can only hold the empty string, so // when the env.var isn't empty, we'll get an ERANGE error (buffer // too small): @@ -3212,7 +3401,7 @@ bool qEnvironmentVariableIsEmpty(const char *varName) Q_DECL_NOEXCEPT are too long will either be truncated or this function will set \a ok to \c false. - \sa qgetenv(), qEnvironmentVariableIsSet() + \sa qgetenv(), qEnvironmentVariable(), qEnvironmentVariableIsSet() */ int qEnvironmentVariableIntValue(const char *varName, bool *ok) Q_DECL_NOEXCEPT { @@ -3221,7 +3410,7 @@ int qEnvironmentVariableIntValue(const char *varName, bool *ok) Q_DECL_NOEXCEPT (std::numeric_limits<uint>::digits + NumBinaryDigitsPerOctalDigit - 1) / NumBinaryDigitsPerOctalDigit; QMutexLocker locker(&environmentMutex); -#if defined(_MSC_VER) && _MSC_VER >= 1400 +#ifdef Q_CC_MSVC // we provide a buffer that can hold any int value: char buffer[MaxDigitsForOctalInt + 2]; // +1 for NUL +1 for optional '-' size_t dummy; @@ -3263,12 +3452,12 @@ int qEnvironmentVariableIntValue(const char *varName, bool *ok) Q_DECL_NOEXCEPT \endcode except that it's potentially much faster, and can't throw exceptions. - \sa qgetenv(), qEnvironmentVariableIsEmpty() + \sa qgetenv(), qEnvironmentVariable(), qEnvironmentVariableIsEmpty() */ bool qEnvironmentVariableIsSet(const char *varName) Q_DECL_NOEXCEPT { QMutexLocker locker(&environmentMutex); -#if defined(_MSC_VER) && _MSC_VER >= 1400 +#ifdef Q_CC_MSVC size_t requiredSize = 0; (void)getenv_s(&requiredSize, 0, 0, varName); return requiredSize != 0; @@ -3293,12 +3482,12 @@ bool qEnvironmentVariableIsSet(const char *varName) Q_DECL_NOEXCEPT uses the replacement function in VC, and calls the standard C library's implementation on all other platforms. - \sa qgetenv() + \sa qgetenv(), qEnvironmentVariable() */ bool qputenv(const char *varName, const QByteArray& value) { QMutexLocker locker(&environmentMutex); -#if defined(_MSC_VER) && _MSC_VER >= 1400 +#if defined(Q_CC_MSVC) return _putenv_s(varName, value.constData()) == 0; #elif (defined(_POSIX_VERSION) && (_POSIX_VERSION-0) >= 200112L) || defined(Q_OS_HAIKU) // POSIX.1-2001 has setenv @@ -3324,12 +3513,12 @@ bool qputenv(const char *varName, const QByteArray& value) \since 5.1 - \sa qputenv(), qgetenv() + \sa qputenv(), qgetenv(), qEnvironmentVariable() */ bool qunsetenv(const char *varName) { QMutexLocker locker(&environmentMutex); -#if defined(_MSC_VER) && _MSC_VER >= 1400 +#if defined(Q_CC_MSVC) return _putenv_s(varName, "") == 0; #elif (defined(_POSIX_VERSION) && (_POSIX_VERSION-0) >= 200112L) || defined(Q_OS_BSD4) || defined(Q_OS_HAIKU) // POSIX.1-2001, BSD and Haiku have unsetenv @@ -3349,138 +3538,6 @@ bool qunsetenv(const char *varName) #endif } -#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) && (__ANDROID_API__ < 21) -typedef QThreadStorage<QJNIObjectPrivate> AndroidRandomStorage; -Q_GLOBAL_STATIC(AndroidRandomStorage, randomTLS) - -#elif defined(Q_OS_UNIX) && !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && (_POSIX_THREAD_SAFE_FUNCTIONS - 0 > 0) - -# if defined(Q_OS_INTEGRITY) && defined(__GHS_VERSION_NUMBER) && (__GHS_VERSION_NUMBER < 500) -// older versions of INTEGRITY used a long instead of a uint for the seed. -typedef long SeedStorageType; -# else -typedef uint SeedStorageType; -# endif - -typedef QThreadStorage<SeedStorageType *> SeedStorage; -Q_GLOBAL_STATIC(SeedStorage, randTLS) // Thread Local Storage for seed value -#endif - -/*! - \relates <QtGlobal> - \since 4.2 - - Thread-safe version of the standard C++ \c srand() function. - - Sets the argument \a seed to be used to generate a new random number sequence of - pseudo random integers to be returned by qrand(). - - The sequence of random numbers generated is deterministic per thread. For example, - if two threads call qsrand(1) and subsequently call qrand(), the threads will get - the same random number sequence. - - \sa qrand() -*/ -void qsrand(uint seed) -{ -#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) && (__ANDROID_API__ < 21) - if (randomTLS->hasLocalData()) { - randomTLS->localData().callMethod<void>("setSeed", "(J)V", jlong(seed)); - return; - } - - QJNIObjectPrivate random("java/util/Random", - "(J)V", - jlong(seed)); - if (!random.isValid()) { - srand(seed); - return; - } - - randomTLS->setLocalData(random); -#elif defined(Q_OS_UNIX) && !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && (_POSIX_THREAD_SAFE_FUNCTIONS - 0 > 0) - SeedStorage *seedStorage = randTLS(); - if (seedStorage) { - SeedStorageType *pseed = seedStorage->localData(); - if (!pseed) - seedStorage->setLocalData(pseed = new SeedStorageType); - *pseed = seed; - } else { - //global static seed storage should always exist, - //except after being deleted by QGlobalStaticDeleter. - //But since it still can be called from destructor of another - //global static object, fallback to srand(seed) - srand(seed); - } -#else - // On Windows srand() and rand() already use Thread-Local-Storage - // to store the seed between calls - // this is also valid for QT_NO_THREAD - srand(seed); -#endif -} - -/*! - \relates <QtGlobal> - \since 4.2 - - Thread-safe version of the standard C++ \c rand() function. - - Returns a value between 0 and \c RAND_MAX (defined in \c <cstdlib> and - \c <stdlib.h>), the next number in the current sequence of pseudo-random - integers. - - Use \c qsrand() to initialize the pseudo-random number generator with - a seed value. - - \sa qsrand() -*/ -int qrand() -{ -#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) && (__ANDROID_API__ < 21) - AndroidRandomStorage *randomStorage = randomTLS(); - if (!randomStorage) - return rand(); - - if (randomStorage->hasLocalData()) { - return randomStorage->localData().callMethod<jint>("nextInt", - "(I)I", - RAND_MAX); - } - - QJNIObjectPrivate random("java/util/Random", - "(J)V", - jlong(1)); - - if (!random.isValid()) - return rand(); - - randomStorage->setLocalData(random); - return random.callMethod<jint>("nextInt", "(I)I", RAND_MAX); -#elif defined(Q_OS_UNIX) && !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && (_POSIX_THREAD_SAFE_FUNCTIONS - 0 > 0) - SeedStorage *seedStorage = randTLS(); - if (seedStorage) { - SeedStorageType *pseed = seedStorage->localData(); - if (!pseed) { - seedStorage->setLocalData(pseed = new SeedStorageType); - *pseed = 1; - } - return rand_r(pseed); - } else { - //global static seed storage should always exist, - //except after being deleted by QGlobalStaticDeleter. - //But since it still can be called from destructor of another - //global static object, fallback to rand() - return rand(); - } -#else - // On Windows srand() and rand() already use Thread-Local-Storage - // to store the seed between calls - // this is also valid for QT_NO_THREAD - return rand(); -#endif -} - /*! \macro forever \relates <QtGlobal> @@ -3553,7 +3610,7 @@ int qrand() */ /*! - \fn qAsConst(T &t) + \fn template <typename T> typename std::add_const<T>::type &qAsConst(T &t) \relates <QtGlobal> \since 5.7 @@ -3605,7 +3662,7 @@ int qrand() */ /*! - \fn qAsConst(const T &&t) + \fn template <typename T> void qAsConst(const T &&t) \relates <QtGlobal> \since 5.7 \overload @@ -4017,43 +4074,6 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters) */ /*! - \macro Q_GLOBAL_STATIC(type, name) - \internal - - Declares a global static variable with the given \a type and \a name. - - Use this macro to instantiate an object in a thread-safe way, creating - a global pointer that can be used to refer to it. - - \warning This macro is subject to a race condition that can cause the object - to be constructed twice. However, if this occurs, the second instance will - be immediately deleted. - - See also - \l{http://www.aristeia.com/publications.html}{"C++ and the perils of Double-Checked Locking"} - by Scott Meyers and Andrei Alexandrescu. -*/ - -/*! - \macro Q_GLOBAL_STATIC_WITH_ARGS(type, name, arguments) - \internal - - Declares a global static variable with the specified \a type and \a name. - - Use this macro to instantiate an object using the \a arguments specified - in a thread-safe way, creating a global pointer that can be used to refer - to it. - - \warning This macro is subject to a race condition that can cause the object - to be constructed twice. However, if this occurs, the second instance will - be immediately deleted. - - See also - \l{http://www.aristeia.com/publications.html}{"C++ and the perils of Double-Checked Locking"} - by Scott Meyers and Andrei Alexandrescu. -*/ - -/*! \macro QT_NAMESPACE \internal @@ -4383,8 +4403,11 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters) stderr. Under Windows, the message is sent to the debugger. On QNX the message is sent to slogger2. This function does nothing if \c QT_NO_WARNING_OUTPUT was defined - during compilation; it exits if the environment variable \c - QT_FATAL_WARNINGS is not empty. + during compilation; it exits if at the nth warning corresponding to the + counter in environment variable \c QT_FATAL_WARNINGS. That is, if the + environment variable contains the value 1, it will exit on the 1st message; + if it contains the value 10, it will exit on the 10th message. Any + non-numeric value is equivalent to 1. This function takes a format string and a list of arguments, similar to the C printf() function. The format should be a Latin-1 |