From d9440df5e9bbc76dbc7d5281c9176a6f26aa173d Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 4 Feb 2014 16:39:44 -0800 Subject: [PATCH] Centralize the handling of all the toXxx (integral) functions By way of templates. This makes the code a lot cleaner. Change-Id: Ie369561c7631b0d34d76a6852883716cc0aa89d4 Reviewed-by: Lars Knoll --- src/corelib/global/qglobal.h | 3 + src/corelib/tools/qbytearray.cpp | 100 ++++++++++------------- src/corelib/tools/qlocale.cpp | 127 +++++++++++------------------- src/corelib/tools/qstring.cpp | 131 +++++++------------------------ src/corelib/tools/qstring.h | 21 +++++ 5 files changed, 140 insertions(+), 242 deletions(-) diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 2a74801c42..0396fbc0c7 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -1029,6 +1029,9 @@ namespace QtPrivate { //like std::enable_if template struct QEnableIf; template struct QEnableIf { typedef T Type; }; + +template struct QConditional { typedef T Type; }; +template struct QConditional { typedef F Type; }; } #ifndef Q_FORWARD_DECLARE_OBJC_CLASS diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp index e9e94c3692..5755bc6ffe 100644 --- a/src/corelib/tools/qbytearray.cpp +++ b/src/corelib/tools/qbytearray.cpp @@ -3266,6 +3266,39 @@ QByteArray QByteArray::rightJustified(int width, char fill, bool truncate) const bool QByteArray::isNull() const { return d == QArrayData::sharedNull(); } +static qlonglong toIntegral_helper(const char *data, bool *ok, int base, qlonglong) +{ + return QLocaleData::bytearrayToLongLong(data, base, ok); +} + +static qulonglong toIntegral_helper(const char *data, bool *ok, int base, qulonglong) +{ + return QLocaleData::bytearrayToUnsLongLong(data, base, ok); +} + +template static inline +T toIntegral_helper(const char *data, bool *ok, int base) +{ + // ### Qt6: use std::conditional::value, qulonglong, qlonglong>::type + const bool isUnsigned = T(0) < T(-1); + typedef typename QtPrivate::QConditional::Type Int64; + +#if defined(QT_CHECK_RANGE) + if (base != 0 && (base < 2 || base > 36)) { + qWarning("QByteArray::toIntegral: Invalid base %d", base); + base = 10; + } +#endif + + // we select the right overload by the last, unused parameter + Int64 val = toIntegral_helper(data, ok, base, Int64()); + if (T(val) != val) { + if (ok) + *ok = false; + val = 0; + } + return T(val); +} /*! Returns the byte array converted to a \c {long long} using base \a @@ -3289,14 +3322,7 @@ bool QByteArray::isNull() const { return d == QArrayData::sharedNull(); } qlonglong QByteArray::toLongLong(bool *ok, int base) const { -#if defined(QT_CHECK_RANGE) - if (base != 0 && (base < 2 || base > 36)) { - qWarning("QByteArray::toLongLong: Invalid base %d", base); - base = 10; - } -#endif - - return QLocaleData::bytearrayToLongLong(nulTerminated().constData(), base, ok); + return toIntegral_helper(nulTerminated().constData(), ok, base); } /*! @@ -3322,17 +3348,9 @@ qlonglong QByteArray::toLongLong(bool *ok, int base) const qulonglong QByteArray::toULongLong(bool *ok, int base) const { -#if defined(QT_CHECK_RANGE) - if (base != 0 && (base < 2 || base > 36)) { - qWarning("QByteArray::toULongLong: Invalid base %d", base); - base = 10; - } -#endif - - return QLocaleData::bytearrayToUnsLongLong(nulTerminated().constData(), base, ok); + return toIntegral_helper(nulTerminated().constData(), ok, base); } - /*! Returns the byte array converted to an \c int using base \a base, which is 10 by default and must be between 2 and 36, or 0. @@ -3357,13 +3375,7 @@ qulonglong QByteArray::toULongLong(bool *ok, int base) const int QByteArray::toInt(bool *ok, int base) const { - qlonglong v = toLongLong(ok, base); - if (v < INT_MIN || v > INT_MAX) { - if (ok) - *ok = false; - v = 0; - } - return int(v); + return toIntegral_helper(nulTerminated().constData(), ok, base); } /*! @@ -3388,13 +3400,7 @@ int QByteArray::toInt(bool *ok, int base) const uint QByteArray::toUInt(bool *ok, int base) const { - qulonglong v = toULongLong(ok, base); - if (v > UINT_MAX) { - if (ok) - *ok = false; - v = 0; - } - return uint(v); + return toIntegral_helper(nulTerminated().constData(), ok, base); } /*! @@ -3422,13 +3428,7 @@ uint QByteArray::toUInt(bool *ok, int base) const */ long QByteArray::toLong(bool *ok, int base) const { - qlonglong v = toLongLong(ok, base); - if (v < LONG_MIN || v > LONG_MAX) { - if (ok) - *ok = false; - v = 0; - } - return long(v); + return toIntegral_helper(nulTerminated().constData(), ok, base); } /*! @@ -3454,13 +3454,7 @@ long QByteArray::toLong(bool *ok, int base) const */ ulong QByteArray::toULong(bool *ok, int base) const { - qulonglong v = toULongLong(ok, base); - if (v > ULONG_MAX) { - if (ok) - *ok = false; - v = 0; - } - return ulong(v); + return toIntegral_helper(nulTerminated().constData(), ok, base); } /*! @@ -3485,13 +3479,7 @@ ulong QByteArray::toULong(bool *ok, int base) const short QByteArray::toShort(bool *ok, int base) const { - qlonglong v = toLongLong(ok, base); - if (v < SHRT_MIN || v > SHRT_MAX) { - if (ok) - *ok = false; - v = 0; - } - return short(v); + return toIntegral_helper(nulTerminated().constData(), ok, base); } /*! @@ -3516,13 +3504,7 @@ short QByteArray::toShort(bool *ok, int base) const ushort QByteArray::toUShort(bool *ok, int base) const { - qulonglong v = toULongLong(ok, base); - if (v > USHRT_MAX) { - if (ok) - *ok = false; - v = 0; - } - return ushort(v); + return toIntegral_helper(nulTerminated().constData(), ok, base); } diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp index f3c492574e..c0e5706af2 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/tools/qlocale.cpp @@ -1061,6 +1061,41 @@ QString QLocale::name() const return result; } +static qlonglong toIntegral_helper(const QLocaleData *d, const QChar *data, int len, bool *ok, + QLocaleData::GroupSeparatorMode mode, qlonglong) +{ + return d->stringToLongLong(data, len, 10, ok, mode); +} + +static qulonglong toIntegral_helper(const QLocaleData *d, const QChar *data, int len, bool *ok, + QLocaleData::GroupSeparatorMode mode, qulonglong) +{ + return d->stringToUnsLongLong(data, len, 10, ok, mode); +} + +template static inline +T toIntegral_helper(const QLocalePrivate *d, const QChar *data, int len, bool *ok) +{ + // ### Qt6: use std::conditional::value, qulonglong, qlonglong>::type + const bool isUnsigned = T(0) < T(-1); + typedef typename QtPrivate::QConditional::Type Int64; + + QLocaleData::GroupSeparatorMode mode + = d->m_numberOptions & QLocale::RejectGroupSeparator + ? QLocaleData::FailOnGroupSeparators + : QLocaleData::ParseGroupSeparators; + + // we select the right overload by the last, unused parameter + Int64 val = toIntegral_helper(d->m_data, data, len, ok, mode, Int64()); + if (T(val) != val) { + if (ok) + *ok = false; + val = 0; + } + return T(val); +} + + /*! \since 4.8 @@ -1135,13 +1170,7 @@ QString QLocale::scriptToString(QLocale::Script script) short QLocale::toShort(const QString &s, bool *ok) const { - qlonglong i = toLongLong(s, ok); - if (i < SHRT_MIN || i > SHRT_MAX) { - if (ok != 0) - *ok = false; - return 0; - } - return short(i); + return toIntegral_helper(d, s.constData(), s.size(), ok); } /*! @@ -1159,13 +1188,7 @@ short QLocale::toShort(const QString &s, bool *ok) const ushort QLocale::toUShort(const QString &s, bool *ok) const { - qulonglong i = toULongLong(s, ok); - if (i > USHRT_MAX) { - if (ok != 0) - *ok = false; - return 0; - } - return ushort(i); + return toIntegral_helper(d, s.constData(), s.size(), ok); } /*! @@ -1183,13 +1206,7 @@ ushort QLocale::toUShort(const QString &s, bool *ok) const int QLocale::toInt(const QString &s, bool *ok) const { - qlonglong i = toLongLong(s, ok); - if (i < INT_MIN || i > INT_MAX) { - if (ok != 0) - *ok = false; - return 0; - } - return int(i); + return toIntegral_helper(d, s.constData(), s.size(), ok); } /*! @@ -1207,13 +1224,7 @@ int QLocale::toInt(const QString &s, bool *ok) const uint QLocale::toUInt(const QString &s, bool *ok) const { - qulonglong i = toULongLong(s, ok); - if (i > UINT_MAX) { - if (ok != 0) - *ok = false; - return 0; - } - return uint(i); + return toIntegral_helper(d, s.constData(), s.size(), ok); } /*! @@ -1232,12 +1243,7 @@ uint QLocale::toUInt(const QString &s, bool *ok) const qlonglong QLocale::toLongLong(const QString &s, bool *ok) const { - QLocaleData::GroupSeparatorMode mode - = d->m_numberOptions & RejectGroupSeparator - ? QLocaleData::FailOnGroupSeparators - : QLocaleData::ParseGroupSeparators; - - return d->m_data->stringToLongLong(s.constData(), s.size(), 10, ok, mode); + return toIntegral_helper(d, s.constData(), s.size(), ok); } /*! @@ -1256,12 +1262,7 @@ qlonglong QLocale::toLongLong(const QString &s, bool *ok) const qulonglong QLocale::toULongLong(const QString &s, bool *ok) const { - QLocaleData::GroupSeparatorMode mode - = d->m_numberOptions & RejectGroupSeparator - ? QLocaleData::FailOnGroupSeparators - : QLocaleData::ParseGroupSeparators; - - return d->m_data->stringToUnsLongLong(s.constData(), s.size(), 10, ok, mode); + return toIntegral_helper(d, s.constData(), s.size(), ok); } /*! @@ -1340,13 +1341,7 @@ double QLocale::toDouble(const QString &s, bool *ok) const short QLocale::toShort(const QStringRef &s, bool *ok) const { - qlonglong i = toLongLong(s, ok); - if (i < SHRT_MIN || i > SHRT_MAX) { - if (ok) - *ok = false; - return 0; - } - return short(i); + return toIntegral_helper(d, s.constData(), s.size(), ok); } /*! @@ -1366,13 +1361,7 @@ short QLocale::toShort(const QStringRef &s, bool *ok) const ushort QLocale::toUShort(const QStringRef &s, bool *ok) const { - qulonglong i = toULongLong(s, ok); - if (i > USHRT_MAX) { - if (ok) - *ok = false; - return 0; - } - return ushort(i); + return toIntegral_helper(d, s.constData(), s.size(), ok); } /*! @@ -1392,13 +1381,7 @@ ushort QLocale::toUShort(const QStringRef &s, bool *ok) const int QLocale::toInt(const QStringRef &s, bool *ok) const { - qlonglong i = toLongLong(s, ok); - if (i < INT_MIN || i > INT_MAX) { - if (ok) - *ok = false; - return 0; - } - return int(i); + return toIntegral_helper(d, s.constData(), s.size(), ok); } /*! @@ -1418,13 +1401,7 @@ int QLocale::toInt(const QStringRef &s, bool *ok) const uint QLocale::toUInt(const QStringRef &s, bool *ok) const { - qulonglong i = toULongLong(s, ok); - if (i > UINT_MAX) { - if (ok) - *ok = false; - return 0; - } - return uint(i); + return toIntegral_helper(d, s.constData(), s.size(), ok); } /*! @@ -1445,12 +1422,7 @@ uint QLocale::toUInt(const QStringRef &s, bool *ok) const qlonglong QLocale::toLongLong(const QStringRef &s, bool *ok) const { - QLocaleData::GroupSeparatorMode mode - = d->m_numberOptions & RejectGroupSeparator - ? QLocaleData::FailOnGroupSeparators - : QLocaleData::ParseGroupSeparators; - - return d->m_data->stringToLongLong(s.constData(), s.size(), 10, ok, mode); + return toIntegral_helper(d, s.constData(), s.size(), ok); } /*! @@ -1471,12 +1443,7 @@ qlonglong QLocale::toLongLong(const QStringRef &s, bool *ok) const qulonglong QLocale::toULongLong(const QStringRef &s, bool *ok) const { - QLocaleData::GroupSeparatorMode mode - = d->m_numberOptions & RejectGroupSeparator - ? QLocaleData::FailOnGroupSeparators - : QLocaleData::ParseGroupSeparators; - - return d->m_data->stringToUnsLongLong(s.constData(), s.size(), 10, ok, mode); + return toIntegral_helper(d, s.constData(), s.size(), ok); } /*! diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 0c0bcac1b6..5bc485be7a 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -6067,17 +6067,23 @@ QString &QString::vsprintf(const char* cformat, va_list ap) */ qint64 QString::toLongLong(bool *ok, int base) const +{ + return toIntegral_helper(constData(), size(), ok, base); +} + +qlonglong QString::toIntegral_helper(const QChar *data, int len, bool *ok, int base) { #if defined(QT_CHECK_RANGE) if (base != 0 && (base < 2 || base > 36)) { - qWarning("QString::toLongLong: Invalid base (%d)", base); + qWarning("QString::toULongLong: Invalid base (%d)", base); base = 10; } #endif - return QLocaleData::c()->stringToLongLong(constData(), size(), base, ok, QLocaleData::FailOnGroupSeparators); + return QLocaleData::c()->stringToLongLong(data, len, base, ok, QLocaleData::FailOnGroupSeparators); } + /*! Returns the string converted to an \c{unsigned long long} using base \a base, which is 10 by default and must be between 2 and 36, or 0. @@ -6101,6 +6107,11 @@ qint64 QString::toLongLong(bool *ok, int base) const */ quint64 QString::toULongLong(bool *ok, int base) const +{ + return toIntegral_helper(constData(), size(), ok, base); +} + +qulonglong QString::toIntegral_helper(const QChar *data, uint len, bool *ok, int base) { #if defined(QT_CHECK_RANGE) if (base != 0 && (base < 2 || base > 36)) { @@ -6109,7 +6120,7 @@ quint64 QString::toULongLong(bool *ok, int base) const } #endif - return QLocaleData::c()->stringToUnsLongLong(constData(), size(), base, ok, QLocaleData::FailOnGroupSeparators); + return QLocaleData::c()->stringToUnsLongLong(data, len, base, ok, QLocaleData::FailOnGroupSeparators); } /*! @@ -6138,13 +6149,7 @@ quint64 QString::toULongLong(bool *ok, int base) const long QString::toLong(bool *ok, int base) const { - qint64 v = toLongLong(ok, base); - if (v < LONG_MIN || v > LONG_MAX) { - if (ok) - *ok = false; - v = 0; - } - return (long)v; + return toIntegral_helper(constData(), size(), ok, base); } /*! @@ -6173,13 +6178,7 @@ long QString::toLong(bool *ok, int base) const ulong QString::toULong(bool *ok, int base) const { - quint64 v = toULongLong(ok, base); - if (v > ULONG_MAX) { - if (ok) - *ok = false; - v = 0; - } - return (ulong)v; + return toIntegral_helper(constData(), size(), ok, base); } @@ -6207,13 +6206,7 @@ ulong QString::toULong(bool *ok, int base) const int QString::toInt(bool *ok, int base) const { - qint64 v = toLongLong(ok, base); - if (v < INT_MIN || v > INT_MAX) { - if (ok) - *ok = false; - v = 0; - } - return v; + return toIntegral_helper(constData(), size(), ok, base); } /*! @@ -6240,13 +6233,7 @@ int QString::toInt(bool *ok, int base) const uint QString::toUInt(bool *ok, int base) const { - quint64 v = toULongLong(ok, base); - if (v > UINT_MAX) { - if (ok) - *ok = false; - v = 0; - } - return (uint)v; + return toIntegral_helper(constData(), size(), ok, base); } /*! @@ -6273,13 +6260,7 @@ uint QString::toUInt(bool *ok, int base) const short QString::toShort(bool *ok, int base) const { - long v = toLongLong(ok, base); - if (v < SHRT_MIN || v > SHRT_MAX) { - if (ok) - *ok = false; - v = 0; - } - return (short)v; + return toIntegral_helper(constData(), size(), ok, base); } /*! @@ -6306,13 +6287,7 @@ short QString::toShort(bool *ok, int base) const ushort QString::toUShort(bool *ok, int base) const { - ulong v = toULongLong(ok, base); - if (v > USHRT_MAX) { - if (ok) - *ok = false; - v = 0; - } - return (ushort)v; + return toIntegral_helper(constData(), size(), ok, base); } @@ -9606,14 +9581,7 @@ QStringRef QStringRef::trimmed() const qint64 QStringRef::toLongLong(bool *ok, int base) const { -#if defined(QT_CHECK_RANGE) - if (base != 0 && (base < 2 || base > 36)) { - qWarning("QString::toLongLong: Invalid base (%d)", base); - base = 10; - } -#endif - - return QLocaleData::c()->stringToLongLong(constData(), size(), base, ok, QLocaleData::FailOnGroupSeparators); + return QString::toIntegral_helper(constData(), size(), ok, base); } /*! @@ -9638,14 +9606,7 @@ qint64 QStringRef::toLongLong(bool *ok, int base) const quint64 QStringRef::toULongLong(bool *ok, int base) const { -#if defined(QT_CHECK_RANGE) - if (base != 0 && (base < 2 || base > 36)) { - qWarning("QString::toULongLong: Invalid base (%d)", base); - base = 10; - } -#endif - - return QLocaleData::c()->stringToUnsLongLong(constData(), size(), base, ok, QLocaleData::FailOnGroupSeparators); + return QString::toIntegral_helper(constData(), size(), ok, base); } /*! @@ -9672,13 +9633,7 @@ quint64 QStringRef::toULongLong(bool *ok, int base) const long QStringRef::toLong(bool *ok, int base) const { - qint64 v = toLongLong(ok, base); - if (v < LONG_MIN || v > LONG_MAX) { - if (ok) - *ok = false; - v = 0; - } - return long(v); + return QString::toIntegral_helper(constData(), size(), ok, base); } /*! @@ -9705,13 +9660,7 @@ long QStringRef::toLong(bool *ok, int base) const ulong QStringRef::toULong(bool *ok, int base) const { - quint64 v = toULongLong(ok, base); - if (v > ULONG_MAX) { - if (ok) - *ok = false; - v = 0; - } - return ulong(v); + return QString::toIntegral_helper(constData(), size(), ok, base); } @@ -9737,13 +9686,7 @@ ulong QStringRef::toULong(bool *ok, int base) const int QStringRef::toInt(bool *ok, int base) const { - qint64 v = toLongLong(ok, base); - if (v < INT_MIN || v > INT_MAX) { - if (ok) - *ok = false; - v = 0; - } - return int(v); + return QString::toIntegral_helper(constData(), size(), ok, base); } /*! @@ -9768,13 +9711,7 @@ int QStringRef::toInt(bool *ok, int base) const uint QStringRef::toUInt(bool *ok, int base) const { - quint64 v = toULongLong(ok, base); - if (v > UINT_MAX) { - if (ok) - *ok = false; - v = 0; - } - return uint(v); + return QString::toIntegral_helper(constData(), size(), ok, base); } /*! @@ -9799,13 +9736,7 @@ uint QStringRef::toUInt(bool *ok, int base) const short QStringRef::toShort(bool *ok, int base) const { - long v = toLongLong(ok, base); - if (v < SHRT_MIN || v > SHRT_MAX) { - if (ok) - *ok = false; - v = 0; - } - return short(v); + return QString::toIntegral_helper(constData(), size(), ok, base); } /*! @@ -9830,13 +9761,7 @@ short QStringRef::toShort(bool *ok, int base) const ushort QStringRef::toUShort(bool *ok, int base) const { - ulong v = toULongLong(ok, base); - if (v > USHRT_MAX) { - if (ok) - *ok = false; - v = 0; - } - return ushort(v); + return QString::toIntegral_helper(constData(), size(), ok, base); } diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index 8fb817d519..9063f59171 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -552,6 +552,7 @@ public: int localeAwareCompare(const QStringRef &s) const; static int localeAwareCompare(const QString& s1, const QStringRef& s2); + // ### Qt6: make inline except for the long long versions short toShort(bool *ok=0, int base=10) const; ushort toUShort(bool *ok=0, int base=10) const; int toInt(bool *ok=0, int base=10) const; @@ -746,6 +747,8 @@ private: static QByteArray toUtf8_helper(const QString &); static QByteArray toLocal8Bit_helper(const QChar *data, int size); static int toUcs4_helper(const ushort *uc, int length, uint *out); + static qlonglong toIntegral_helper(const QChar *data, int len, bool *ok, int base); + static qulonglong toIntegral_helper(const QChar *data, uint len, bool *ok, int base); void replace_helper(uint *indices, int nIndices, int blen, const QChar *after, int alen); friend class QCharRef; friend class QTextCodec; @@ -754,6 +757,24 @@ private: friend class QCollator; friend struct QAbstractConcatenable; + template static + T toIntegral_helper(const QChar *data, int len, bool *ok, int base) + { + // ### Qt6: use std::conditional::value, qulonglong, qlonglong>::type + const bool isUnsigned = T(0) < T(-1); + typedef typename QtPrivate::QConditional::Type Int64; + typedef typename QtPrivate::QConditional::Type Int32; + + // we select the right overload by casting size() to int or uint + Int64 val = toIntegral_helper(data, Int32(len), ok, base); + if (T(val) != val) { + if (ok) + *ok = false; + val = 0; + } + return T(val); + } + public: typedef Data * DataPtr; inline DataPtr &data_ptr() { return d; }