diff options
Diffstat (limited to 'src/corelib/tools/qstring.cpp')
-rw-r--r-- | src/corelib/tools/qstring.cpp | 224 |
1 files changed, 117 insertions, 107 deletions
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 89d9889b2f..55289fa0e7 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -40,6 +40,7 @@ #include <qtextcodec.h> #endif #include <private/qutfcodec_p.h> +#include <private/qlocale_tools_p.h> #include "qsimd_p.h" #include <qnumeric.h> #include <qdatastream.h> @@ -1651,9 +1652,7 @@ QString::QString(QChar ch) \snippet qstring/main.cpp 45 If you want to append a certain number of identical characters to - the string, use \l operator+=() as follows rather than resize(): - - \snippet qstring/main.cpp 46 + the string, use the \l {QString::}{resize(int, QChar)} overload. If you want to expand the string so that it reaches a certain width and fill the new positions with a particular character, use @@ -1684,6 +1683,25 @@ void QString::resize(int size) } } +/*! + \overload + \since 5.7 + + Unlike \l {QString::}{resize(int)}, this overload + initializes the new characters to \a fillChar: + + \snippet qstring/main.cpp 46 +*/ + +void QString::resize(int size, QChar fillChar) +{ + const int oldSize = length(); + resize(size); + const int difference = length() - oldSize; + if (difference > 0) + std::fill_n(d->begin() + oldSize, difference, fillChar.unicode()); +} + /*! \fn int QString::capacity() const Returns the maximum number of characters that can be stored in @@ -2681,7 +2699,7 @@ QString &QString::replace(QChar c, QLatin1String after, Qt::CaseSensitivity cs) expect. Consider sorting user-interface strings with localeAwareCompare(). */ -bool operator==(const QString &s1, const QString &s2) +bool operator==(const QString &s1, const QString &s2) Q_DECL_NOTHROW { if (s1.d->size != s2.d->size) return false; @@ -2694,7 +2712,7 @@ bool operator==(const QString &s1, const QString &s2) Returns \c true if this string is equal to \a other; otherwise returns \c false. */ -bool QString::operator==(QLatin1String other) const +bool QString::operator==(QLatin1String other) const Q_DECL_NOTHROW { if (d->size != other.size()) return false; @@ -2745,7 +2763,7 @@ bool QString::operator==(QLatin1String other) const expect. Consider sorting user-interface strings using the QString::localeAwareCompare() function. */ -bool operator<(const QString &s1, const QString &s2) +bool operator<(const QString &s1, const QString &s2) Q_DECL_NOTHROW { return ucstrcmp(s1.constData(), s1.length(), s2.constData(), s2.length()) < 0; } @@ -2755,7 +2773,7 @@ bool operator<(const QString &s1, const QString &s2) Returns \c true if this string is lexically less than the parameter string called \a other; otherwise returns \c false. */ -bool QString::operator<(QLatin1String other) const +bool QString::operator<(QLatin1String other) const Q_DECL_NOTHROW { const uchar *c = (const uchar *) other.latin1(); if (!c || *c == 0) @@ -2860,7 +2878,7 @@ bool QString::operator<(QLatin1String other) const Returns \c true if this string is lexically greater than the parameter string \a other; otherwise returns \c false. */ -bool QString::operator>(QLatin1String other) const +bool QString::operator>(QLatin1String other) const Q_DECL_NOTHROW { const uchar *c = (const uchar *) other.latin1(); if (!c || *c == '\0') @@ -3562,7 +3580,7 @@ QString &QString::replace(const QRegularExpression &re, const QString &after) lastEnd = 0; // add the after string, with replacements for the backreferences - foreach (const QStringCapture &backReference, backReferences) { + for (const QStringCapture &backReference : qAsConst(backReferences)) { // part of "after" before the backreference len = backReference.pos - lastEnd; if (len > 0) { @@ -3600,7 +3618,7 @@ QString &QString::replace(const QRegularExpression &re, const QString &after) resize(newLength); int i = 0; QChar *uc = data(); - foreach (const QStringRef &chunk, chunks) { + for (const QStringRef &chunk : qAsConst(chunks)) { int len = chunk.length(); memcpy(uc + i, chunk.unicode(), len * sizeof(QChar)); i += len; @@ -5343,7 +5361,7 @@ QString& QString::fill(QChar ch, int size) Same as compare(*this, \a other, \a cs). */ -int QString::compare(const QString &other, Qt::CaseSensitivity cs) const +int QString::compare(const QString &other, Qt::CaseSensitivity cs) const Q_DECL_NOTHROW { if (cs == Qt::CaseSensitive) return ucstrcmp(constData(), length(), other.constData(), other.length()); @@ -5355,7 +5373,7 @@ int QString::compare(const QString &other, Qt::CaseSensitivity cs) const \since 4.5 */ int QString::compare_helper(const QChar *data1, int length1, const QChar *data2, int length2, - Qt::CaseSensitivity cs) + Qt::CaseSensitivity cs) Q_DECL_NOTHROW { if (cs == Qt::CaseSensitive) return ucstrcmp(data1, length1, data2, length2); @@ -5370,7 +5388,7 @@ int QString::compare_helper(const QChar *data1, int length1, const QChar *data2, Same as compare(*this, \a other, \a cs). */ -int QString::compare(QLatin1String other, Qt::CaseSensitivity cs) const +int QString::compare(QLatin1String other, Qt::CaseSensitivity cs) const Q_DECL_NOTHROW { return compare_helper(unicode(), length(), other, cs); } @@ -5406,7 +5424,7 @@ int QString::compare_helper(const QChar *data1, int length1, const char *data2, \since 4.5 */ int QString::compare_helper(const QChar *data1, int length1, QLatin1String s2, - Qt::CaseSensitivity cs) + Qt::CaseSensitivity cs) Q_DECL_NOTHROW { const ushort *uc = reinterpret_cast<const ushort *>(data1); const ushort *uce = uc + length1; @@ -5877,6 +5895,72 @@ QString &QString::vsprintf(const char *cformat, va_list ap) return *this = vasprintf(cformat, ap); } +static void append_utf8(QString &qs, const char *cs, int len) +{ + const int oldSize = qs.size(); + qs.resize(oldSize + len); + const QChar *newEnd = QUtf8::convertToUnicode(qs.data() + oldSize, cs, len); + qs.resize(newEnd - qs.constData()); +} + +static uint parse_flag_characters(const char * &c) Q_DECL_NOTHROW +{ + uint flags = QLocaleData::ZeroPadExponent; + while (true) { + switch (*c) { + case '#': flags |= QLocaleData::Alternate; break; + case '0': flags |= QLocaleData::ZeroPadded; break; + case '-': flags |= QLocaleData::LeftAdjusted; break; + case ' ': flags |= QLocaleData::BlankBeforePositive; break; + case '+': flags |= QLocaleData::AlwaysShowSign; break; + case '\'': flags |= QLocaleData::ThousandsGroup; break; + default: return flags; + } + ++c; + } +} + +static int parse_field_width(const char * &c) +{ + Q_ASSERT(qIsDigit(*c)); + + // can't be negative - started with a digit + // contains at least one digit + const char *endp; + bool ok; + const qulonglong result = qstrtoull(c, &endp, 10, &ok); + c = endp; + while (qIsDigit(*c)) // preserve Qt 5.5 behavior of consuming all digits, no matter how many + ++c; + return ok && result < qulonglong(std::numeric_limits<int>::max()) ? int(result) : 0; +} + +enum LengthMod { lm_none, lm_hh, lm_h, lm_l, lm_ll, lm_L, lm_j, lm_z, lm_t }; + +static inline bool can_consume(const char * &c, char ch) Q_DECL_NOTHROW +{ + if (*c == ch) { + ++c; + return true; + } + return false; +} + +static LengthMod parse_length_modifier(const char * &c) Q_DECL_NOTHROW +{ + switch (*c++) { + case 'h': return can_consume(c, 'h') ? lm_hh : lm_h; + case 'l': return can_consume(c, 'l') ? lm_ll : lm_l; + case 'L': return lm_L; + case 'j': return lm_j; + case 'z': + case 'Z': return lm_z; + case 't': return lm_t; + } + --c; // don't consume *c - it wasn't a flag + return lm_none; +} + /*! \fn QString::vasprintf(const char *cformat, va_list ap) \since 5.5 @@ -5907,7 +5991,7 @@ QString QString::vasprintf(const char *cformat, va_list ap) const char *cb = c; while (*c != '\0' && *c != '%') c++; - result.append(QString::fromUtf8(cb, (int)(c - cb))); + append_utf8(result, cb, int(c - cb)); if (*c == '\0') break; @@ -5926,23 +6010,7 @@ QString QString::vasprintf(const char *cformat, va_list ap) continue; } - // Parse flag characters - uint flags = 0; - bool no_more_flags = false; - do { - switch (*c) { - case '#': flags |= QLocaleData::Alternate; break; - case '0': flags |= QLocaleData::ZeroPadded; break; - case '-': flags |= QLocaleData::LeftAdjusted; break; - case ' ': flags |= QLocaleData::BlankBeforePositive; break; - case '+': flags |= QLocaleData::AlwaysShowSign; break; - case '\'': flags |= QLocaleData::ThousandsGroup; break; - default: no_more_flags = true; break; - } - - if (!no_more_flags) - ++c; - } while (!no_more_flags); + uint flags = parse_flag_characters(c); if (*c == '\0') { result.append(QLatin1String(escape_start)); // incomplete escape, treat as non-escape text @@ -5952,15 +6020,8 @@ QString QString::vasprintf(const char *cformat, va_list ap) // Parse field width int width = -1; // -1 means unspecified if (qIsDigit(*c)) { - QString width_str; - while (*c != '\0' && qIsDigit(*c)) - width_str.append(QLatin1Char(*c++)); - - // can't be negative - started with a digit - // contains at least one digit - width = width_str.toInt(); - } - else if (*c == '*') { + width = parse_field_width(c); + } else if (*c == '*') { // can't parse this in another function, not portably, at least width = va_arg(ap, int); if (width < 0) width = -1; // treat all negative numbers as unspecified @@ -5977,15 +6038,8 @@ QString QString::vasprintf(const char *cformat, va_list ap) if (*c == '.') { ++c; if (qIsDigit(*c)) { - QString precision_str; - while (*c != '\0' && qIsDigit(*c)) - precision_str.append(QLatin1Char(*c++)); - - // can't be negative - started with a digit - // contains at least one digit - precision = precision_str.toInt(); - } - else if (*c == '*') { + precision = parse_field_width(c); + } else if (*c == '*') { // can't parse this in another function, not portably, at least precision = va_arg(ap, int); if (precision < 0) precision = -1; // treat all negative numbers as unspecified @@ -5998,53 +6052,7 @@ QString QString::vasprintf(const char *cformat, va_list ap) break; } - // Parse the length modifier - enum LengthMod { lm_none, lm_hh, lm_h, lm_l, lm_ll, lm_L, lm_j, lm_z, lm_t }; - LengthMod length_mod = lm_none; - switch (*c) { - case 'h': - ++c; - if (*c == 'h') { - length_mod = lm_hh; - ++c; - } - else - length_mod = lm_h; - break; - - case 'l': - ++c; - if (*c == 'l') { - length_mod = lm_ll; - ++c; - } - else - length_mod = lm_l; - break; - - case 'L': - ++c; - length_mod = lm_L; - break; - - case 'j': - ++c; - length_mod = lm_j; - break; - - case 'z': - case 'Z': - ++c; - length_mod = lm_z; - break; - - case 't': - ++c; - length_mod = lm_t; - break; - - default: break; - } + const LengthMod length_mod = parse_length_modifier(c); if (*c == '\0') { result.append(QLatin1String(escape_start)); // incomplete escape, treat as non-escape text @@ -6186,8 +6194,7 @@ QString QString::vasprintf(const char *cformat, va_list ap) } case lm_ll: { qint64 *n = va_arg(ap, qint64*); - volatile uint tmp = result.length(); // egcs-2.91.66 gets internal - *n = tmp; // compiler error without volatile + *n = result.length(); break; } default: { @@ -6250,7 +6257,7 @@ qlonglong QString::toIntegral_helper(const QChar *data, int len, bool *ok, int b } #endif - return QLocaleData::c()->stringToLongLong(data, len, base, ok, QLocaleData::FailOnGroupSeparators); + return QLocaleData::c()->stringToLongLong(data, len, base, ok, QLocale::RejectGroupSeparator); } @@ -6290,7 +6297,8 @@ qulonglong QString::toIntegral_helper(const QChar *data, uint len, bool *ok, int } #endif - return QLocaleData::c()->stringToUnsLongLong(data, len, base, ok, QLocaleData::FailOnGroupSeparators); + return QLocaleData::c()->stringToUnsLongLong(data, len, base, ok, + QLocale::RejectGroupSeparator); } /*! @@ -6491,7 +6499,7 @@ ushort QString::toUShort(bool *ok, int base) const double QString::toDouble(bool *ok) const { - return QLocaleData::c()->stringToDouble(constData(), size(), ok, QLocaleData::FailOnGroupSeparators); + return QLocaleData::c()->stringToDouble(constData(), size(), ok, QLocale::RejectGroupSeparator); } /*! @@ -7739,6 +7747,8 @@ QString QString::arg(double a, int fieldWidth, char fmt, int prec, QChar fillCha if (!(locale.numberOptions() & QLocale::OmitGroupSeparator)) flags |= QLocaleData::ThousandsGroup; + if (!(locale.numberOptions() & QLocale::OmitLeadingZeroInExponent)) + flags |= QLocaleData::ZeroPadExponent; locale_arg = locale.d->m_data->doubleToString(a, prec, form, fieldWidth, flags); } @@ -8925,7 +8935,7 @@ QString QStringRef::toString() const { Returns \c true if string reference \a s1 is lexically equal to string reference \a s2; otherwise returns \c false. */ -bool operator==(const QStringRef &s1,const QStringRef &s2) +bool operator==(const QStringRef &s1,const QStringRef &s2) Q_DECL_NOTHROW { return (s1.size() == s2.size() && qMemEquals((const ushort *)s1.unicode(), (const ushort *)s2.unicode(), s1.size())); } @@ -8935,7 +8945,7 @@ bool operator==(const QStringRef &s1,const QStringRef &s2) Returns \c true if string \a s1 is lexically equal to string reference \a s2; otherwise returns \c false. */ -bool operator==(const QString &s1,const QStringRef &s2) +bool operator==(const QString &s1,const QStringRef &s2) Q_DECL_NOTHROW { return (s1.size() == s2.size() && qMemEquals((const ushort *)s1.unicode(), (const ushort *)s2.unicode(), s1.size())); } @@ -8945,7 +8955,7 @@ bool operator==(const QString &s1,const QStringRef &s2) Returns \c true if string \a s1 is lexically equal to string reference \a s2; otherwise returns \c false. */ -bool operator==(QLatin1String s1, const QStringRef &s2) +bool operator==(QLatin1String s1, const QStringRef &s2) Q_DECL_NOTHROW { if (s1.size() != s2.size()) return false; @@ -8967,7 +8977,7 @@ bool operator==(QLatin1String s1, const QStringRef &s2) expect. Consider sorting user-interface strings using the QString::localeAwareCompare() function. */ -bool operator<(const QStringRef &s1,const QStringRef &s2) +bool operator<(const QStringRef &s1,const QStringRef &s2) Q_DECL_NOTHROW { return ucstrcmp(s1.constData(), s1.length(), s2.constData(), s2.length()) < 0; } @@ -10459,7 +10469,7 @@ ushort QStringRef::toUShort(bool *ok, int base) const double QStringRef::toDouble(bool *ok) const { - return QLocaleData::c()->stringToDouble(constData(), size(), ok, QLocaleData::FailOnGroupSeparators); + return QLocaleData::c()->stringToDouble(constData(), size(), ok, QLocale::RejectGroupSeparator); } /*! |