Advertisement
Guest User

Untitled

a guest
Jun 22nd, 2017
77
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 54.23 KB | None | 0 0
  1. From b0e7cc60369b9952e56549e921b69237f7377a65 Mon Sep 17 00:00:00 2001
  2. From: Denis Dzyubenko <denis.dzyubenko@nokia.com>
  3. Date: Fri, 15 Oct 2010 13:37:10 +0200
  4. Subject: [PATCH] Added functions to QString to use QStringRef more.
  5.  
  6. Also modified a few places in Qt where using QStringRef should be preferred.
  7.  
  8. Reviewed-by: pending
  9. ---
  10. src/corelib/io/qresource.cpp            |   14 +-
  11.  src/corelib/io/qurl.cpp                 |   31 +-
  12.  src/corelib/kernel/qcoreapplication.cpp |    5 +-
  13.  src/corelib/kernel/qmetaobject.cpp      |    5 +-
  14.  src/corelib/tools/qdatetime.cpp         |   28 +-
  15.  src/corelib/tools/qlocale.cpp           |   63 +++-
  16.  src/corelib/tools/qlocale.h             |    1 +
  17.  src/corelib/tools/qlocale_p.h           |    5 +-
  18.  src/corelib/tools/qstring.cpp           |  698 ++++++++++++++++++++++++++++++-
  19.  src/corelib/tools/qstring.h             |   52 +++-
  20.  src/testlib/qtest.h                     |   16 +
  21.  tests/auto/qstring/tst_qstring.cpp      |   80 ++++-
  22.  12 files changed, 937 insertions(+), 61 deletions(-)
  23.  
  24. diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp
  25. index 929885c..b39a75e 100644
  26. --- a/src/corelib/io/qresource.cpp
  27. +++ b/src/corelib/io/qresource.cpp
  28. @@ -316,7 +316,7 @@ QResourcePrivate::ensureInitialized() const
  29.  
  30.      QString path = fileName;
  31.      if(path.startsWith(QLatin1Char(':')))
  32. -        path = path.mid(1);
  33. +        path.remove(0, 1);
  34.  
  35.      if(path.startsWith(QLatin1Char('/'))) {
  36.          that->load(path);
  37. @@ -343,7 +343,7 @@ QResourcePrivate::ensureChildren() const
  38.  
  39.      QString path = absoluteFilePath, k;
  40.      if(path.startsWith(QLatin1Char(':')))
  41. -        path = path.mid(1);
  42. +        path.remove(0, 1);
  43.      QSet<QString> kids;
  44.      QString cleaned = cleanPath(path);
  45.      for(int i = 0; i < related.size(); ++i) {
  46. @@ -641,7 +641,7 @@ int QResourceRoot::findNode(const QString &_path, const QLocale &locale) const
  47.                  if(!root.endsWith(QLatin1Char('/')))
  48.                      root += QLatin1Char('/');
  49.                  if(path.size() >= root.size() && path.startsWith(root))
  50. -                    path = path.mid(root.length()-1);
  51. +                    path.remove(0, root.length()-1);
  52.                  if(path.isEmpty())
  53.                      path = QLatin1Char('/');
  54.              }
  55. @@ -816,8 +816,8 @@ bool QResourceRoot::mappingRootSubdir(const QString &path, QString *match) const
  56.  {
  57.      const QString root = mappingRoot();
  58.      if(!root.isEmpty()) {
  59. -        const QStringList root_segments = root.split(QLatin1Char('/'), QString::SkipEmptyParts),
  60. -                          path_segments = path.split(QLatin1Char('/'), QString::SkipEmptyParts);
  61. +        const QList<QStringRef> root_segments = root.splitRef(QLatin1Char('/'), QString::SkipEmptyParts),
  62. +                                path_segments = path.splitRef(QLatin1Char('/'), QString::SkipEmptyParts);
  63.          if(path_segments.size() <= root_segments.size()) {
  64.              int matched = 0;
  65.              for(int i = 0; i < path_segments.size(); ++i) {
  66. @@ -827,7 +827,7 @@ bool QResourceRoot::mappingRootSubdir(const QString &path, QString *match) const
  67.              }
  68.              if(matched == path_segments.size()) {
  69.                  if(match && root_segments.size() > matched)
  70. -                    *match = root_segments.at(matched);
  71. +                    *match = root_segments.at(matched).toString();
  72.                  return true;
  73.              }
  74.          }
  75. @@ -1040,7 +1040,7 @@ public:
  76.  static QString qt_resource_fixResourceRoot(QString r) {
  77.      if(!r.isEmpty()) {
  78.          if(r.startsWith(QLatin1Char(':')))
  79. -            r = r.mid(1);
  80. +            r = r.remove(0, 1);
  81.          if(!r.isEmpty())
  82.              r = QDir::cleanPath(r);
  83.      }
  84. diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp
  85. index 6452c0f..951fa40 100644
  86. --- a/src/corelib/io/qurl.cpp
  87. +++ b/src/corelib/io/qurl.cpp
  88. @@ -203,6 +203,15 @@ extern void q_normalizePercentEncoding(QByteArray *ba, const char *exclude);
  89.  extern void q_toPercentEncoding(QByteArray *ba, const char *exclude, const char *include = 0);
  90.  extern void q_fromPercentEncoding(QByteArray *ba);
  91.  
  92. +static QByteArray toPercentEncodingHelper(const QStringRef &s, const char *exclude, const char *include = 0)
  93. +{
  94. +    if (s.isNull())
  95. +        return QByteArray();    // null
  96. +    QByteArray ba = s.toUtf8();
  97. +    q_toPercentEncoding(&ba, exclude, include);
  98. +    return ba;
  99. +}
  100. +
  101.  static QByteArray toPercentEncodingHelper(const QString &s, const char *exclude, const char *include = 0)
  102.  {
  103.      if (s.isNull())
  104. @@ -302,7 +311,7 @@ public:
  105.      void ensureEncodedParts() const;
  106.      QString authority(QUrl::FormattingOptions options = QUrl::None) const;
  107.      void setAuthority(const QString &auth);
  108. -    void setUserInfo(const QString &userInfo);
  109. +    void setUserInfo(const QStringRef &userInfo);
  110.      QString userInfo(QUrl::FormattingOptions options = QUrl::None) const;
  111.      void setEncodedAuthority(const QByteArray &authority);
  112.      void setEncodedUserInfo(const QUrlParseData *parseData);
  113. @@ -3542,7 +3551,7 @@ void QUrlPrivate::setAuthority(const QString &auth)
  114.  {
  115.      isHostValid = true;
  116.      if (auth.isEmpty()) {
  117. -        setUserInfo(QString());
  118. +        setUserInfo(QStringRef());
  119.          host.clear();
  120.          port = -1;
  121.          return;
  122. @@ -3579,7 +3588,7 @@ void QUrlPrivate::setAuthority(const QString &auth)
  123.  
  124.      int userInfoIndex = auth.indexOf(QLatin1Char('@'));
  125.      if (userInfoIndex != -1 && (portIndex == -1 || userInfoIndex < portIndex))
  126. -        setUserInfo(auth.left(userInfoIndex));
  127. +        setUserInfo(auth.leftRef(userInfoIndex));
  128.  
  129.      int hostIndex = 0;
  130.      if (userInfoIndex != -1)
  131. @@ -3588,22 +3597,22 @@ void QUrlPrivate::setAuthority(const QString &auth)
  132.      if (portIndex != -1)
  133.          hostLength -= (auth.length() - portIndex);
  134.  
  135. -    host = auth.mid(hostIndex, hostLength).trimmed();
  136. +    host = auth.midRef(hostIndex, hostLength).trimmedRef().toString();
  137.  }
  138.  
  139. -void QUrlPrivate::setUserInfo(const QString &userInfo)
  140. +void QUrlPrivate::setUserInfo(const QStringRef &userInfo)
  141.  {
  142.      encodedUserName.clear();
  143.      encodedPassword.clear();
  144.  
  145.      int delimIndex = userInfo.indexOf(QLatin1Char(':'));
  146.      if (delimIndex == -1) {
  147. -        userName = userInfo;
  148. +        userName = userInfo.toString();
  149.          password.clear();
  150.          return;
  151.      }
  152. -    userName = userInfo.left(delimIndex);
  153. -    password = userInfo.right(userInfo.length() - delimIndex - 1);
  154. +    userName = userInfo.leftRef(delimIndex).toString();
  155. +    password = userInfo.rightRef(userInfo.length() - delimIndex - 1).toString();
  156.  }
  157.  
  158.  void QUrlPrivate::setEncodedUserInfo(const QUrlParseData *parseData)
  159. @@ -4338,8 +4347,8 @@ void QUrl::setUrl(const QString &url, ParsingMode parsingMode)
  160.      }
  161.      QByteArray encodedUrl;
  162.      if (start != -1) {
  163. -        QString hostPart = tmp.left(start);
  164. -        QString otherPart = tmp.mid(start);
  165. +        QStringRef hostPart = tmp.leftRef(start);
  166. +        QStringRef otherPart = tmp.midRef(start);
  167.          encodedUrl = toPercentEncodingHelper(hostPart, ":/?#[]@!$&'()*+,;=")
  168.                     + toPercentEncodingHelper(otherPart, ":/?#@!$&'()*+,;=");
  169.      } else {
  170. @@ -4540,7 +4549,7 @@ void QUrl::setUserInfo(const QString &userInfo)
  171.      detach();
  172.      QURL_UNSETFLAG(d->stateFlags, QUrlPrivate::Validated | QUrlPrivate::Normalized);
  173.  
  174. -    d->setUserInfo(userInfo.trimmed());
  175. +    d->setUserInfo(QStringRef(&userInfo).trimmedRef());
  176.  }
  177.  
  178.  /*!
  179. diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
  180. index e967884..751d9da 100644
  181. --- a/src/corelib/kernel/qcoreapplication.cpp
  182. +++ b/src/corelib/kernel/qcoreapplication.cpp
  183. @@ -1988,8 +1988,9 @@ QString QCoreApplication::applicationFilePath()
  184.          */
  185.          QByteArray pEnv = qgetenv("PATH");
  186.          QDir currentDir = QDir::current();
  187. -        QStringList paths = QString::fromLocal8Bit(pEnv.constData()).split(QLatin1Char(':'));
  188. -        for (QStringList::const_iterator p = paths.constBegin(); p != paths.constEnd(); ++p) {
  189. +        QString path = QString::fromLocal8Bit(pEnv.constData());
  190. +        QList<QStringRef> paths = path.splitRef(QLatin1Char(':'));
  191. +        for (QList<QStringRef>::const_iterator p = paths.constBegin(); p != paths.constEnd(); ++p) {
  192.              if ((*p).isEmpty())
  193.                  continue;
  194.              QString candidate = currentDir.absoluteFilePath(*p + QLatin1Char('/') + argv0);
  195. diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp
  196. index ceb2a9c..7d92e19 100644
  197. --- a/src/corelib/kernel/qmetaobject.cpp
  198. +++ b/src/corelib/kernel/qmetaobject.cpp
  199. @@ -1898,13 +1898,14 @@ int QMetaEnum::keysToValue(const char *keys) const
  200.  {
  201.      if (!mobj)
  202.          return -1;
  203. -    QStringList l = QString::fromLatin1(keys).split(QLatin1Char('|'));
  204. +    QString keysStr = QString::fromLatin1(keys);
  205. +    QList<QStringRef> l = keysStr.splitRef(QLatin1Char('|'));
  206.      //#### TODO write proper code, do not use QStringList
  207.      int value = 0;
  208.      int count = mobj->d.data[handle + 2];
  209.      int data = mobj->d.data[handle + 3];
  210.      for (int li = 0; li < l.size(); ++li) {
  211. -        QString trimmed = l.at(li).trimmed();
  212. +        QStringRef trimmed = l.at(li).trimmedRef();
  213.          QByteArray qualified_key = trimmed.toLatin1();
  214.          const char *key = qualified_key.constData();
  215.          uint scope = 0;
  216. diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp
  217. index ab7530d..2dbac9b 100644
  218. --- a/src/corelib/tools/qdatetime.cpp
  219. +++ b/src/corelib/tools/qdatetime.cpp
  220. @@ -1170,13 +1170,13 @@ QDate QDate::fromString(const QString& s, Qt::DateFormat f)
  221.      default:
  222.  #ifndef QT_NO_TEXTDATE
  223.      case Qt::TextDate: {
  224. -        QStringList parts = s.split(QLatin1Char(' '), QString::SkipEmptyParts);
  225. +        QList<QStringRef> parts = s.splitRef(QLatin1Char(' '), QString::SkipEmptyParts);
  226.  
  227.          if (parts.count() != 4) {
  228.              return QDate();
  229.          }
  230.  
  231. -        QString monthName = parts.at(1);
  232. +        QStringRef monthName = parts.at(1);
  233.          int month = -1;
  234.          // Assume that English monthnames are the default
  235.          for (int i = 0; i < 12; ++i) {
  236. @@ -1831,13 +1831,13 @@ QTime QTime::fromString(const QString& s, Qt::DateFormat f)
  237.      default:
  238.          {
  239.              bool ok = true;
  240. -            const int hour(s.mid(0, 2).toInt(&ok));
  241. +            const int hour(s.midRef(0, 2).toInt(&ok));
  242.              if (!ok)
  243.                  return QTime();
  244. -            const int minute(s.mid(3, 2).toInt(&ok));
  245. +            const int minute(s.midRef(3, 2).toInt(&ok));
  246.              if (!ok)
  247.                  return QTime();
  248. -            const int second(s.mid(6, 2).toInt(&ok));
  249. +            const int second(s.midRef(6, 2).toInt(&ok));
  250.              if (!ok)
  251.                  return QTime();
  252.              const QString msec_s(QLatin1String("0.") + s.mid(9, 4));
  253. @@ -3265,7 +3265,7 @@ int QDateTime::utcOffset() const
  254.  
  255.  #ifndef QT_NO_DATESTRING
  256.  
  257. -static int fromShortMonthName(const QString &monthName)
  258. +static int fromShortMonthName(const QStringRef &monthName)
  259.  {
  260.      // Assume that English monthnames are the default
  261.      for (int i = 0; i < 12; ++i) {
  262. @@ -3348,7 +3348,7 @@ QDateTime QDateTime::fromString(const QString& s, Qt::DateFormat f)
  263.                                                                                       : QLocale::ShortFormat));
  264.  #if !defined(QT_NO_TEXTDATE)
  265.      case Qt::TextDate: {
  266. -        QStringList parts = s.split(QLatin1Char(' '), QString::SkipEmptyParts);
  267. +        QList<QStringRef> parts = s.splitRef(QLatin1Char(' '), QString::SkipEmptyParts);
  268.  
  269.          if ((parts.count() < 5) || (parts.count() > 6)) {
  270.              return QDateTime();
  271. @@ -3369,7 +3369,7 @@ QDateTime QDateTime::fromString(const QString& s, Qt::DateFormat f)
  272.              // first variant failed, lets try the other
  273.              month = fromShortMonthName(parts.at(2));
  274.              if (month != -1) {
  275. -                QString dayStr = parts.at(1);
  276. +                QStringRef dayStr = parts.at(1);
  277.                  if (dayStr.endsWith(QLatin1Char('.'))) {
  278.                      dayStr.chop(1);
  279.                      day = dayStr.toInt(&ok);
  280. @@ -3387,13 +3387,13 @@ QDateTime QDateTime::fromString(const QString& s, Qt::DateFormat f)
  281.          }
  282.  
  283.          int year;
  284. -        QStringList timeParts = parts.at(3).split(QLatin1Char(':'));
  285. +        QList<QStringRef> timeParts = parts.at(3).splitRef(QLatin1Char(':'));
  286.          if ((timeParts.count() == 3) || (timeParts.count() == 2)) {
  287.              year = parts.at(4).toInt(&ok);
  288.              if (!ok)
  289.                  return QDateTime();
  290.          } else {
  291. -            timeParts = parts.at(4).split(QLatin1Char(':'));
  292. +            timeParts = parts.at(4).splitRef(QLatin1Char(':'));
  293.              if ((timeParts.count() != 3) && (timeParts.count() != 2))
  294.                  return QDateTime();
  295.              year = parts.at(3).toInt(&ok);
  296. @@ -3422,7 +3422,7 @@ QDateTime QDateTime::fromString(const QString& s, Qt::DateFormat f)
  297.          if (parts.count() == 5)
  298.              return QDateTime(date, time, Qt::LocalTime);
  299.  
  300. -        QString tz = parts.at(5);
  301. +        QStringRef tz = parts.at(5);
  302.          if (!tz.startsWith(QLatin1String("GMT"), Qt::CaseInsensitive))
  303.              return QDateTime();
  304.          int tzoffset = 0;
  305. @@ -3432,10 +3432,10 @@ QDateTime QDateTime::fromString(const QString& s, Qt::DateFormat f)
  306.                  && (sign != QLatin1Char('-'))) {
  307.                  return QDateTime();
  308.              }
  309. -            int tzhour = tz.mid(4, 2).toInt(&ok);
  310. +            int tzhour = tz.midRef(4, 2).toInt(&ok);
  311.              if (!ok)
  312.                  return QDateTime();
  313. -            int tzminute = tz.mid(6).toInt(&ok);
  314. +            int tzminute = tz.midRef(6).toInt(&ok);
  315.              if (!ok)
  316.                  return QDateTime();
  317.              tzoffset = (tzhour*60 + tzminute) * 60;
  318. @@ -5472,7 +5472,7 @@ int QDateTimeParser::findAmPm(QString &str, int index, int *used) const
  319.      }
  320.      if (used)
  321.          *used = str.size();
  322. -    if (str.trimmed().isEmpty()) {
  323. +    if (str.trimmedRef().isEmpty()) {
  324.          return PossibleBoth;
  325.      }
  326.      const QLatin1Char space(' ');
  327. diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp
  328. index 6b1de5e..f33dd39 100644
  329. --- a/src/corelib/tools/qlocale.cpp
  330. +++ b/src/corelib/tools/qlocale.cpp
  331. @@ -4322,23 +4322,23 @@ static bool removeGroupSeparators(QLocalePrivate::CharBuff *num)
  332.      number. We can't detect junk here, since we don't even know the base
  333.      of the number.
  334.  */
  335. -bool QLocalePrivate::numberToCLocale(const QString &num,
  336. -                                            GroupSeparatorMode group_sep_mode,
  337. -                                            CharBuff *result) const
  338. +bool QLocalePrivate::numberToCLocale(const QStringRef &num,
  339. +                                     GroupSeparatorMode group_sep_mode,
  340. +                                     CharBuff *result) const
  341.  {
  342.      const QChar *uc = num.unicode();
  343. -    int l = num.length();
  344. +    int len = num.length();
  345.      int idx = 0;
  346.  
  347.      // Skip whitespace
  348. -    while (idx < l && uc[idx].isSpace())
  349. +    while (idx < len && uc[idx].isSpace())
  350.          ++idx;
  351. -    if (idx == l)
  352. +    if (idx == len)
  353.          return false;
  354.  
  355.      const QChar _group = group();
  356.  
  357. -    while (idx < l) {
  358. +    while (idx < len) {
  359.          const QChar &in = uc[idx];
  360.  
  361.          char out = digitToCLocale(in);
  362. @@ -4362,7 +4362,7 @@ bool QLocalePrivate::numberToCLocale(const QString &num,
  363.      }
  364.  
  365.      // Check trailing whitespace
  366. -    for (; idx < l; ++idx) {
  367. +    for (; idx < len; ++idx) {
  368.          if (!uc[idx].isSpace())
  369.              return false;
  370.      }
  371. @@ -4475,7 +4475,7 @@ double QLocalePrivate::stringToDouble(const QString &number, bool *ok,
  372.                                          GroupSeparatorMode group_sep_mode) const
  373.  {
  374.      CharBuff buff;
  375. -    if (!numberToCLocale(group().unicode() == 0xa0 ? number.trimmed() : number,
  376. +    if (!numberToCLocale(group().unicode() == 0xa0 ? number.trimmedRef() : QStringRef(&number),
  377.                           group_sep_mode, &buff)) {
  378.          if (ok != 0)
  379.              *ok = false;
  380. @@ -4488,7 +4488,7 @@ qlonglong QLocalePrivate::stringToLongLong(const QString &number, int base,
  381.                                             bool *ok, GroupSeparatorMode group_sep_mode) const
  382.  {
  383.      CharBuff buff;
  384. -    if (!numberToCLocale(group().unicode() == 0xa0 ? number.trimmed() : number,
  385. +    if (!numberToCLocale(group().unicode() == 0xa0 ? number.trimmedRef() : QStringRef(&number),
  386.                           group_sep_mode, &buff)) {
  387.          if (ok != 0)
  388.              *ok = false;
  389. @@ -4502,7 +4502,7 @@ qulonglong QLocalePrivate::stringToUnsLongLong(const QString &number, int base,
  390.                                                 bool *ok, GroupSeparatorMode group_sep_mode) const
  391.  {
  392.      CharBuff buff;
  393. -    if (!numberToCLocale(group().unicode() == 0xa0 ? number.trimmed() : number,
  394. +    if (!numberToCLocale(group().unicode() == 0xa0 ? number.trimmedRef() : QStringRef(&number),
  395.                           group_sep_mode, &buff)) {
  396.          if (ok != 0)
  397.              *ok = false;
  398. @@ -4513,6 +4513,47 @@ qulonglong QLocalePrivate::stringToUnsLongLong(const QString &number, int base,
  399.  }
  400.  
  401.  
  402. +double QLocalePrivate::stringToDouble(const QStringRef &number, bool *ok,
  403. +                                      GroupSeparatorMode group_sep_mode) const
  404. +{
  405. +    CharBuff buff;
  406. +    if (!numberToCLocale(group().unicode() == 0xa0 ? number.trimmedRef() : number,
  407. +                         group_sep_mode, &buff)) {
  408. +        if (ok != 0)
  409. +            *ok = false;
  410. +        return 0.0;
  411. +    }
  412. +    return bytearrayToDouble(buff.constData(), ok);
  413. +}
  414. +
  415. +qlonglong QLocalePrivate::stringToLongLong(const QStringRef &number, int base,
  416. +                                           bool *ok, GroupSeparatorMode group_sep_mode) const
  417. +{
  418. +    CharBuff buff;
  419. +    if (!numberToCLocale(group().unicode() == 0xa0 ? number.trimmedRef() : number,
  420. +                         group_sep_mode, &buff)) {
  421. +        if (ok != 0)
  422. +            *ok = false;
  423. +        return 0;
  424. +    }
  425. +
  426. +    return bytearrayToLongLong(buff.constData(), base, ok);
  427. +}
  428. +
  429. +qulonglong QLocalePrivate::stringToUnsLongLong(const QStringRef &number, int base,
  430. +                                               bool *ok, GroupSeparatorMode group_sep_mode) const
  431. +{
  432. +    CharBuff buff;
  433. +    if (!numberToCLocale(group().unicode() == 0xa0 ? number.trimmedRef() : number,
  434. +                         group_sep_mode, &buff)) {
  435. +        if (ok != 0)
  436. +            *ok = false;
  437. +        return 0;
  438. +    }
  439. +
  440. +    return bytearrayToUnsLongLong(buff.constData(), base, ok);
  441. +}
  442. +
  443.  double QLocalePrivate::bytearrayToDouble(const char *num, bool *ok, bool *overflow)
  444.  {
  445.      if (ok != 0)
  446. diff --git a/src/corelib/tools/qlocale.h b/src/corelib/tools/qlocale.h
  447. index 8b424bb..795168b 100644
  448. --- a/src/corelib/tools/qlocale.h
  449. +++ b/src/corelib/tools/qlocale.h
  450. @@ -112,6 +112,7 @@ class Q_CORE_EXPORT QLocale
  451.      Q_ENUMS(Language)
  452.      Q_ENUMS(Country)
  453.      friend class QString;
  454. +    friend class QStringRef;
  455.      friend class QByteArray;
  456.      friend class QIntValidator;
  457.      friend class QDoubleValidator;
  458. diff --git a/src/corelib/tools/qlocale_p.h b/src/corelib/tools/qlocale_p.h
  459. index 6205745..669c184 100644
  460. --- a/src/corelib/tools/qlocale_p.h
  461. +++ b/src/corelib/tools/qlocale_p.h
  462. @@ -125,13 +125,16 @@ public:
  463.      qint64 stringToLongLong(const QString &num, int base, bool *ok, GroupSeparatorMode group_sep_mode) const;
  464.      quint64 stringToUnsLongLong(const QString &num, int base, bool *ok, GroupSeparatorMode group_sep_mode) const;
  465.  
  466. +    double stringToDouble(const QStringRef &num, bool *ok, GroupSeparatorMode group_sep_mode) const;
  467. +    qint64 stringToLongLong(const QStringRef &num, int base, bool *ok, GroupSeparatorMode group_sep_mode) const;
  468. +    quint64 stringToUnsLongLong(const QStringRef &num, int base, bool *ok, GroupSeparatorMode group_sep_mode) const;
  469.  
  470.      static double bytearrayToDouble(const char *num, bool *ok, bool *overflow = 0);
  471.      static qint64 bytearrayToLongLong(const char *num, int base, bool *ok, bool *overflow = 0);
  472.      static quint64 bytearrayToUnsLongLong(const char *num, int base, bool *ok);
  473.  
  474.      typedef QVarLengthArray<char, 256> CharBuff;
  475. -    bool numberToCLocale(const QString &num,
  476. +    bool numberToCLocale(const QStringRef &num,
  477.                           GroupSeparatorMode group_sep_mode,
  478.                            CharBuff *result) const;
  479.      inline char digitToCLocale(const QChar &c) const;
  480. diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
  481. index cfffc4a..04ebb82 100644
  482. --- a/src/corelib/tools/qstring.cpp
  483. +++ b/src/corelib/tools/qstring.cpp
  484. @@ -1723,6 +1723,20 @@ QString &QString::remove(const QString &str, Qt::CaseSensitivity cs)
  485.  }
  486.  
  487.  /*!
  488. +    \since 4.8
  489. +    \overload
  490. +*/
  491. +QString &QString::remove(const QStringRef &str, Qt::CaseSensitivity cs)
  492. +{
  493. +    if (str.string()) {
  494. +        int i = 0;
  495. +        while ((i = indexOf(str, i, cs)) != -1)
  496. +            remove(i, str.size());
  497. +    }
  498. +    return *this;
  499. +}
  500. +
  501. +/*!
  502.    Removes every occurrence of the character \a ch in this string, and
  503.    returns a reference to this string.
  504.  
  505. @@ -3216,7 +3230,7 @@ int QString::count(const QRegExp& rx) const
  506.  
  507.  QString QString::section(const QString &sep, int start, int end, SectionFlags flags) const
  508.  {
  509. -    QStringList sections = split(sep, KeepEmptyParts,
  510. +    QList<QStringRef> sections = splitRef(sep, KeepEmptyParts,
  511.                                   (flags & SectionCaseInsensitiveSeps) ? Qt::CaseInsensitive : Qt::CaseSensitive);
  512.      if (sections.isEmpty())
  513.          return QString();
  514. @@ -3240,7 +3254,7 @@ QString QString::section(const QString &sep, int start, int end, SectionFlags fl
  515.      QString ret;
  516.      int first_i = start, last_i = end;
  517.      for (int i = 0; x <= end && i < sections.size(); ++i) {
  518. -        QString section = sections.at(i);
  519. +        QStringRef section = sections.at(i);
  520.          const bool empty = section.isEmpty();
  521.          if (x >= start) {
  522.              if(x == start)
  523. @@ -3264,9 +3278,9 @@ QString QString::section(const QString &sep, int start, int end, SectionFlags fl
  524.  #ifndef QT_NO_REGEXP
  525.  class qt_section_chunk {
  526.  public:
  527. -    qt_section_chunk(int l, QString s) { length = l; string = s; }
  528. +    qt_section_chunk(int l, QStringRef s) { length = l; string = s; }
  529.      int length;
  530. -    QString string;
  531. +    QStringRef string;
  532.  };
  533.  
  534.  /*!
  535. @@ -3295,12 +3309,12 @@ QString QString::section(const QRegExp &reg, int start, int end, SectionFlags fl
  536.      QList<qt_section_chunk> sections;
  537.      int n = length(), m = 0, last_m = 0, last_len = 0;
  538.      while ((m = sep.indexIn(*this, m)) != -1) {
  539. -        sections.append(qt_section_chunk(last_len, QString(uc + last_m, m - last_m)));
  540. +        sections.append(qt_section_chunk(last_len, midRef(last_m, m - last_m)));
  541.          last_m = m;
  542.          last_len = sep.matchedLength();
  543.          m += qMax(sep.matchedLength(), 1);
  544.      }
  545. -    sections.append(qt_section_chunk(last_len, QString(uc + last_m, n - last_m)));
  546. +    sections.append(qt_section_chunk(last_len, midRef(last_m, n - last_m)));
  547.  
  548.      if(start < 0)
  549.          start += sections.count();
  550. @@ -3321,18 +3335,18 @@ QString QString::section(const QRegExp &reg, int start, int end, SectionFlags fl
  551.              if(x != start)
  552.                  ret += section.string;
  553.              else
  554. -                ret += section.string.mid(section.length);
  555. +                ret += section.string.midRef(section.length);
  556.          }
  557.          if (!empty || !(flags & SectionSkipEmpty))
  558.              x++;
  559.      }
  560.      if((flags & SectionIncludeLeadingSep) && first_i < sections.size()) {
  561.          const qt_section_chunk &section = sections.at(first_i);
  562. -        ret.prepend(section.string.left(section.length));
  563. +        ret.prepend(section.string.leftRef(section.length));
  564.      }
  565.      if((flags & SectionIncludeTrailingSep) && last_i+1 <= sections.size()-1) {
  566.          const qt_section_chunk &section = sections.at(last_i+1);
  567. -        ret += section.string.left(section.length);
  568. +        ret += section.string.leftRef(section.length);
  569.      }
  570.      return ret;
  571.  }
  572. @@ -4142,9 +4156,10 @@ QString QString::simplified() const
  573.  
  574.      \snippet doc/src/snippets/qstring/main.cpp 82
  575.  
  576. -    Unlike simplified(), trimmed() leaves internal whitespace alone.
  577. +    Unlike simplified(), trimmed() and trimmedRef() leave internal whitespace
  578. +    alone.
  579.  
  580. -    \sa simplified()
  581. +    \sa simplified(), trimmedRef()
  582.  */
  583.  QString QString::trimmed() const
  584.  {
  585. @@ -4169,6 +4184,23 @@ QString QString::trimmed() const
  586.      return QString(s + start, l);
  587.  }
  588.  
  589. +/*!
  590. +    \since 4.8
  591. +
  592. +    Returns a reference to a substring that has whitespace removed from the
  593. +    start and the end.
  594. +
  595. +    Whitespace means any character for which QChar::isSpace() returns
  596. +    true. This includes the ASCII characters '\\t', '\\n', '\\v',
  597. +    '\\f', '\\r', and ' '.
  598. +
  599. +    Unlike simplified(), trimmed() and trimmedRef() leave internal whitespace alone.
  600. +*/
  601. +QStringRef QString::trimmedRef() const
  602. +{
  603. +    return QStringRef(this).trimmedRef();
  604. +}
  605. +
  606.  /*! \fn const QChar QString::at(int position) const
  607.  
  608.      Returns the character at the given index \a position in the
  609. @@ -6086,6 +6118,36 @@ QStringList QString::split(const QString &sep, SplitBehavior behavior, Qt::CaseS
  610.  }
  611.  
  612.  /*!
  613. +    \since 4.8
  614. +    \overload
  615. +*/
  616. +QStringList QString::split(const QLatin1String &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
  617. +{
  618. +    return split(QString(sep), behavior, cs);
  619. +}
  620. +
  621. +/*!
  622. +    \since 4.8
  623. +    \overload
  624. +*/
  625. +QStringList QString::split(const QStringRef &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
  626. +{
  627. +    QStringList list;
  628. +    int start = 0;
  629. +    int extra = 0;
  630. +    int end;
  631. +    while ((end = indexOf(sep, start + extra, cs)) != -1) {
  632. +        if (start != end || behavior == KeepEmptyParts)
  633. +            list.append(mid(start, end - start));
  634. +        start = end + sep.size();
  635. +        extra = (sep.size() == 0 ? 1 : 0);
  636. +    }
  637. +    if (start != size() || behavior == KeepEmptyParts)
  638. +        list.append(mid(start));
  639. +    return list;
  640. +}
  641. +
  642. +/*!
  643.      \overload
  644.  */
  645.  QStringList QString::split(const QChar &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
  646. @@ -6103,6 +6165,77 @@ QStringList QString::split(const QChar &sep, SplitBehavior behavior, Qt::CaseSen
  647.      return list;
  648.  }
  649.  
  650. +/*!
  651. +    \since 4.8
  652. +    \overload
  653. +*/
  654. +QList<QStringRef> QString::splitRef(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
  655. +{
  656. +    QList<QStringRef> list;
  657. +    int start = 0;
  658. +    int extra = 0;
  659. +    int end;
  660. +    while ((end = indexOf(sep, start + extra, cs)) != -1) {
  661. +        if (start != end || behavior == KeepEmptyParts)
  662. +            list.append(midRef(start, end - start));
  663. +        start = end + sep.size();
  664. +        extra = (sep.size() == 0 ? 1 : 0);
  665. +    }
  666. +    if (start != size() || behavior == KeepEmptyParts)
  667. +        list.append(midRef(start));
  668. +    return list;
  669. +}
  670. +
  671. +/*!
  672. +    \since 4.8
  673. +    \overload
  674. +*/
  675. +QList<QStringRef> QString::splitRef(const QStringRef &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
  676. +{
  677. +    QList<QStringRef> list;
  678. +    int start = 0;
  679. +    int extra = 0;
  680. +    int end;
  681. +    while ((end = indexOf(sep, start + extra, cs)) != -1) {
  682. +        if (start != end || behavior == KeepEmptyParts)
  683. +            list.append(midRef(start, end - start));
  684. +        start = end + sep.size();
  685. +        extra = (sep.size() == 0 ? 1 : 0);
  686. +    }
  687. +    if (start != size() || behavior == KeepEmptyParts)
  688. +        list.append(midRef(start));
  689. +    return list;
  690. +}
  691. +
  692. +/*!
  693. +    \since 4.8
  694. +    \overload
  695. +*/
  696. +QList<QStringRef> QString::splitRef(const QLatin1String &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
  697. +{
  698. +    return splitRef(QString(sep), behavior, cs);
  699. +}
  700. +
  701. +/*!
  702. +    \since 4.8
  703. +    \overload
  704. +*/
  705. +QList<QStringRef> QString::splitRef(const QChar &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
  706. +{
  707. +    QList<QStringRef> list;
  708. +    int start = 0;
  709. +    int end;
  710. +    while ((end = indexOf(sep, start, cs)) != -1) {
  711. +        if (start != end || behavior == KeepEmptyParts)
  712. +            list.append(midRef(start, end - start));
  713. +        start = end + 1;
  714. +    }
  715. +    if (start != size() || behavior == KeepEmptyParts)
  716. +        list.append(midRef(start));
  717. +    return list;
  718. +}
  719. +
  720. +
  721.  #ifndef QT_NO_REGEXP
  722.  /*!
  723.      \overload
  724. @@ -6148,6 +6281,29 @@ QStringList QString::split(const QRegExp &rx, SplitBehavior behavior) const
  725.          list.append(mid(start));
  726.      return list;
  727.  }
  728. +
  729. +/*!
  730. +    \since 4.8
  731. +    \overload
  732. +*/
  733. +QList<QStringRef> QString::splitRef(const QRegExp &rx, SplitBehavior behavior) const
  734. +{
  735. +    QRegExp rx2(rx);
  736. +    QList<QStringRef> list;
  737. +    int start = 0;
  738. +    int extra = 0;
  739. +    int end;
  740. +    while ((end = rx2.indexIn(*this, start + extra)) != -1) {
  741. +        int matchedLen = rx2.matchedLength();
  742. +        if (start != end || behavior == KeepEmptyParts)
  743. +            list.append(midRef(start, end - start));
  744. +        start = end + matchedLen;
  745. +        extra = (matchedLen == 0) ? 1 : 0;
  746. +    }
  747. +    if (start != size() || behavior == KeepEmptyParts)
  748. +        list.append(midRef(start));
  749. +    return list;
  750. +}
  751.  #endif
  752.  
  753.  /*!
  754. @@ -9096,4 +9252,524 @@ QVector<uint> QStringRef::toUcs4() const
  755.      return v;
  756.  }
  757.  
  758. +/*!
  759. +    \since 4.8
  760. +    \overload
  761. +*/
  762. +QList<QStringRef> QStringRef::splitRef(const QString &sep, QString::SplitBehavior behavior, Qt::CaseSensitivity cs) const
  763. +{
  764. +    QList<QStringRef> list;
  765. +    int start = 0;
  766. +    int extra = 0;
  767. +    int end;
  768. +    while ((end = indexOf(sep, start + extra, cs)) != -1) {
  769. +        if (start != end || behavior == QString::KeepEmptyParts)
  770. +            list.append(midRef(start, end - start));
  771. +        start = end + sep.size();
  772. +        extra = (sep.size() == 0 ? 1 : 0);
  773. +    }
  774. +    if (start != size() || behavior == QString::KeepEmptyParts)
  775. +        list.append(midRef(start));
  776. +    return list;
  777. +}
  778. +
  779. +/*!
  780. +    \since 4.8
  781. +    \overload
  782. +*/
  783. +QList<QStringRef> QStringRef::splitRef(const QStringRef &sep, QString::SplitBehavior behavior, Qt::CaseSensitivity cs) const
  784. +{
  785. +    QList<QStringRef> list;
  786. +    int start = 0;
  787. +    int extra = 0;
  788. +    int end;
  789. +    while ((end = indexOf(sep, start + extra, cs)) != -1) {
  790. +        if (start != end || behavior == QString::KeepEmptyParts)
  791. +            list.append(midRef(start, end - start));
  792. +        start = end + sep.size();
  793. +        extra = (sep.size() == 0 ? 1 : 0);
  794. +    }
  795. +    if (start != size() || behavior == QString::KeepEmptyParts)
  796. +        list.append(midRef(start));
  797. +    return list;
  798. +}
  799. +
  800. +/*!
  801. +    \since 4.8
  802. +    \overload
  803. +*/
  804. +QList<QStringRef> QStringRef::splitRef(const QLatin1String &sep, QString::SplitBehavior behavior, Qt::CaseSensitivity cs) const
  805. +{
  806. +    return splitRef(QString(sep), behavior, cs);
  807. +}
  808. +
  809. +/*!
  810. +    \since 4.8
  811. +    \overload
  812. +*/
  813. +QList<QStringRef> QStringRef::splitRef(const QChar &sep, QString::SplitBehavior behavior, Qt::CaseSensitivity cs) const
  814. +{
  815. +    QList<QStringRef> list;
  816. +    int start = 0;
  817. +    int end;
  818. +    while ((end = indexOf(sep, start, cs)) != -1) {
  819. +        if (start != end || behavior == QString::KeepEmptyParts)
  820. +            list.append(midRef(start, end - start));
  821. +        start = end + 1;
  822. +    }
  823. +    if (start != size() || behavior == QString::KeepEmptyParts)
  824. +        list.append(midRef(start));
  825. +    return list;
  826. +}
  827. +
  828. +/*!
  829. +    \since 4.8
  830. +    Returns the string converted to a \c{long long} using base \a
  831. +    base, which is 10 by default and must be between 2 and 36, or 0.
  832. +    Returns 0 if the conversion fails.
  833. +
  834. +    If a conversion error occurs, *\a{ok} is set to false; otherwise
  835. +    *\a{ok} is set to true.
  836. +
  837. +    If \a base is 0, the C language convention is used: If the string
  838. +    begins with "0x", base 16 is used; if the string begins with "0",
  839. +    base 8 is used; otherwise, base 10 is used.
  840. +
  841. +    \sa toULongLong(), toInt()
  842. +*/
  843. +qint64 QStringRef::toLongLong(bool *ok, int base) const
  844. +{
  845. +    if (!m_string || m_size == 0)
  846. +        return 0;
  847. +
  848. +#if defined(QT_CHECK_RANGE)
  849. +    if (base != 0 && (base < 2 || base > 36)) {
  850. +        qWarning("QString::toLongLong: Invalid base (%d)", base);
  851. +        base = 10;
  852. +    }
  853. +#endif
  854. +
  855. +    bool my_ok;
  856. +    QLocale def_locale;
  857. +    qint64 result = def_locale.d()->stringToLongLong(*this, base, &my_ok, QLocalePrivate::FailOnGroupSeparators);
  858. +    if (my_ok) {
  859. +        if (ok != 0)
  860. +            *ok = true;
  861. +        return result;
  862. +    }
  863. +
  864. +    QLocale c_locale(QLocale::C);
  865. +    return c_locale.d()->stringToLongLong(*this, base, ok, QLocalePrivate::FailOnGroupSeparators);
  866. +}
  867. +
  868. +/*!
  869. +    \since 4.8
  870. +    Returns the string converted to an \c{unsigned long long} using base \a
  871. +    base, which is 10 by default and must be between 2 and 36, or 0.
  872. +    Returns 0 if the conversion fails.
  873. +
  874. +    If a conversion error occurs, *\a{ok} is set to false; otherwise
  875. +    *\a{ok} is set to true.
  876. +
  877. +    If \a base is 0, the C language convention is used: If the string
  878. +    begins with "0x", base 16 is used; if the string begins with "0",
  879. +    base 8 is used; otherwise, base 10 is used.
  880. +
  881. +    \sa toLongLong()
  882. +*/
  883. +quint64 QStringRef::toULongLong(bool *ok, int base) const
  884. +{
  885. +#if defined(QT_CHECK_RANGE)
  886. +    if (base != 0 && (base < 2 || base > 36)) {
  887. +        qWarning("QString::toULongLong: Invalid base (%d)", base);
  888. +        base = 10;
  889. +    }
  890. +#endif
  891. +
  892. +    bool my_ok;
  893. +    QLocale def_locale;
  894. +    quint64 result = def_locale.d()->stringToUnsLongLong(*this, base, &my_ok, QLocalePrivate::FailOnGroupSeparators);
  895. +    if (my_ok) {
  896. +        if (ok != 0)
  897. +            *ok = true;
  898. +        return result;
  899. +    }
  900. +
  901. +    QLocale c_locale(QLocale::C);
  902. +    return c_locale.d()->stringToUnsLongLong(*this, base, ok, QLocalePrivate::FailOnGroupSeparators);
  903. +}
  904. +
  905. +/*!
  906. +    \since 4.8
  907. +
  908. +    Returns the string converted to a \c long using base \a
  909. +    base, which is 10 by default and must be between 2 and 36, or 0.
  910. +    Returns 0 if the conversion fails.
  911. +
  912. +    If a conversion error occurs, *\a{ok} is set to false; otherwise
  913. +    *\a{ok} is set to true.
  914. +
  915. +    If \a base is 0, the C language convention is used: If the string
  916. +    begins with "0x", base 16 is used; if the string begins with "0",
  917. +    base 8 is used; otherwise, base 10 is used.
  918. +
  919. +
  920. +    \sa toULong(), toInt()
  921. +*/
  922. +long QStringRef::toLong(bool *ok, int base) const
  923. +{
  924. +    qint64 v = toLongLong(ok, base);
  925. +    if (v < LONG_MIN || v > LONG_MAX) {
  926. +        if (ok)
  927. +            *ok = false;
  928. +        v = 0;
  929. +    }
  930. +    return (long)v;
  931. +}
  932. +
  933. +/*!
  934. +    \since 4.8
  935. +
  936. +    Returns the string converted to an \c{unsigned long} using base \a
  937. +    base, which is 10 by default and must be between 2 and 36, or 0.
  938. +    Returns 0 if the conversion fails.
  939. +
  940. +    If a conversion error occurs, *\a{ok} is set to false; otherwise
  941. +    *\a{ok} is set to true.
  942. +
  943. +    If \a base is 0, the C language convention is used: If the string
  944. +    begins with "0x", base 16 is used; if the string begins with "0",
  945. +    base 8 is used; otherwise, base 10 is used.
  946. +*/
  947. +ulong QStringRef::toULong(bool *ok, int base) const
  948. +{
  949. +    quint64 v = toULongLong(ok, base);
  950. +    if (v > ULONG_MAX) {
  951. +        if (ok)
  952. +            *ok = false;
  953. +        v = 0;
  954. +    }
  955. +    return (ulong)v;
  956. +}
  957. +
  958. +
  959. +/*!
  960. +    \since 4.8
  961. +    Returns the string converted to an \c int using base \a
  962. +    base, which is 10 by default and must be between 2 and 36, or 0.
  963. +    Returns 0 if the conversion fails.
  964. +
  965. +    If a conversion error occurs, *\a{ok} is set to false; otherwise
  966. +    *\a{ok} is set to true.
  967. +
  968. +    If \a base is 0, the C language convention is used: If the string
  969. +    begins with "0x", base 16 is used; if the string begins with "0",
  970. +    base 8 is used; otherwise, base 10 is used.
  971. +
  972. +    \sa toUInt(), toDouble()
  973. +*/
  974. +int QStringRef::toInt(bool *ok, int base) const
  975. +{
  976. +    qint64 v = toLongLong(ok, base);
  977. +    if (v < INT_MIN || v > INT_MAX) {
  978. +        if (ok)
  979. +            *ok = false;
  980. +        v = 0;
  981. +    }
  982. +    return v;
  983. +}
  984. +
  985. +/*!
  986. +    \since 4.8
  987. +    Returns the string converted to an \c{unsigned int} using base \a
  988. +    base, which is 10 by default and must be between 2 and 36, or 0.
  989. +    Returns 0 if the conversion fails.
  990. +
  991. +    If a conversion error occurs, *\a{ok} is set to false; otherwise
  992. +    *\a{ok} is set to true.
  993. +
  994. +    If \a base is 0, the C language convention is used: If the string
  995. +    begins with "0x", base 16 is used; if the string begins with "0",
  996. +    base 8 is used; otherwise, base 10 is used.
  997. +
  998. +    \sa toInt()
  999. +*/
  1000. +uint QStringRef::toUInt(bool *ok, int base) const
  1001. +{
  1002. +    quint64 v = toULongLong(ok, base);
  1003. +    if (v > UINT_MAX) {
  1004. +        if (ok)
  1005. +            *ok = false;
  1006. +        v = 0;
  1007. +    }
  1008. +    return (uint)v;
  1009. +}
  1010. +
  1011. +/*!
  1012. +    \since 4.8
  1013. +
  1014. +    Returns the string converted to a \c short using base \a
  1015. +    base, which is 10 by default and must be between 2 and 36, or 0.
  1016. +    Returns 0 if the conversion fails.
  1017. +
  1018. +    If a conversion error occurs, *\a{ok} is set to false; otherwise
  1019. +    *\a{ok} is set to true.
  1020. +
  1021. +    If \a base is 0, the C language convention is used: If the string
  1022. +    begins with "0x", base 16 is used; if the string begins with "0",
  1023. +    base 8 is used; otherwise, base 10 is used.
  1024. +
  1025. +    \sa toUShort(), toInt()
  1026. +*/
  1027. +short QStringRef::toShort(bool *ok, int base) const
  1028. +{
  1029. +    long v = toLongLong(ok, base);
  1030. +    if (v < SHRT_MIN || v > SHRT_MAX) {
  1031. +        if (ok)
  1032. +            *ok = false;
  1033. +        v = 0;
  1034. +    }
  1035. +    return (short)v;
  1036. +}
  1037. +
  1038. +/*!
  1039. +    \since 4.8
  1040. +    Returns the string converted to an \c{unsigned short} using base \a
  1041. +    base, which is 10 by default and must be between 2 and 36, or 0.
  1042. +    Returns 0 if the conversion fails.
  1043. +
  1044. +    If a conversion error occurs, *\a{ok} is set to false; otherwise
  1045. +    *\a{ok} is set to true.
  1046. +
  1047. +    If \a base is 0, the C language convention is used: If the string
  1048. +    begins with "0x", base 16 is used; if the string begins with "0",
  1049. +    base 8 is used; otherwise, base 10 is used.
  1050. +
  1051. +    \sa toShort()
  1052. +*/
  1053. +ushort QStringRef::toUShort(bool *ok, int base) const
  1054. +{
  1055. +    ulong v = toULongLong(ok, base);
  1056. +    if (v > USHRT_MAX) {
  1057. +        if (ok)
  1058. +            *ok = false;
  1059. +        v = 0;
  1060. +    }
  1061. +    return (ushort)v;
  1062. +}
  1063. +
  1064. +
  1065. +/*!
  1066. +    \since 4.8
  1067. +    Returns the string converted to a \c double value.
  1068. +
  1069. +    Returns 0.0 if the conversion fails.
  1070. +
  1071. +    If a conversion error occurs, \c{*}\a{ok} is set to false;
  1072. +    otherwise \c{*}\a{ok} is set to true.
  1073. +
  1074. +    \snippet doc/src/snippets/qstring/main.cpp 66
  1075. +
  1076. +    Various string formats for floating point numbers can be converted
  1077. +    to double values:
  1078. +
  1079. +    \snippet doc/src/snippets/qstring/main.cpp 67
  1080. +
  1081. +    This function tries to interpret the string according to the
  1082. +    current locale. The current locale is determined from the
  1083. +    system at application startup and can be changed by calling
  1084. +    QLocale::setDefault(). If the string cannot be interpreted
  1085. +    according to the current locale, this function falls back
  1086. +    on the "C" locale.
  1087. +
  1088. +    \snippet doc/src/snippets/qstring/main.cpp 69
  1089. +    \snippet doc/src/snippets/qstring/main.cpp 70
  1090. +
  1091. +    Due to the ambiguity between the decimal point and thousands group
  1092. +    separator in various locales, this function does not handle
  1093. +    thousands group separators. If you need to convert such numbers,
  1094. +    see QLocale::toDouble().
  1095. +
  1096. +    \snippet doc/src/snippets/qstring/main.cpp 68
  1097. +
  1098. +    \sa QLocale::setDefault() QLocale::toDouble() trimmedRef()
  1099. +*/
  1100. +
  1101. +double QStringRef::toDouble(bool *ok) const
  1102. +{
  1103. +    bool my_ok;
  1104. +    QLocale def_locale;
  1105. +    double result = def_locale.d()->stringToDouble(*this, &my_ok, QLocalePrivate::FailOnGroupSeparators);
  1106. +    if (my_ok) {
  1107. +        if (ok != 0)
  1108. +            *ok = true;
  1109. +        return result;
  1110. +    }
  1111. +
  1112. +    QLocale c_locale(QLocale::C);
  1113. +    return c_locale.d()->stringToDouble(*this, ok, QLocalePrivate::FailOnGroupSeparators);
  1114. +}
  1115. +
  1116. +/*!
  1117. +    \since 4.8
  1118. +    Returns the string converted to a \c float value.
  1119. +
  1120. +    If a conversion error occurs, *\a{ok} is set to false; otherwise
  1121. +    *\a{ok} is set to true. Returns 0.0 if the conversion fails.
  1122. +
  1123. +    \sa toDouble(), toInt()
  1124. +*/
  1125. +float QStringRef::toFloat(bool *ok) const
  1126. +{
  1127. +    bool myOk;
  1128. +    double d = toDouble(&myOk);
  1129. +    if (!myOk || d > QT_MAX_FLOAT || d < -QT_MAX_FLOAT) {
  1130. +        if (ok != 0)
  1131. +            *ok = false;
  1132. +        return 0.0;
  1133. +    }
  1134. +    if (ok != 0)
  1135. +        *ok = true;
  1136. +    return (float) d;
  1137. +}
  1138. +
  1139. +/*!
  1140. +    \since 4.8
  1141. +
  1142. +    Returns a reference to a substring that contains the \a n leftmost characters
  1143. +    of the string.
  1144. +
  1145. +    The entire string is returned if \a n is greater than size() or
  1146. +    less than zero.
  1147. +
  1148. +    \sa rightRef(), midRef(), startsWith()
  1149. +*/
  1150. +QStringRef QStringRef::leftRef(int n) const
  1151. +{
  1152. +    if (n >= m_size || n < 0 || !m_string)
  1153. +        return *this;
  1154. +    return QStringRef(m_string, m_position, n);
  1155. +}
  1156. +
  1157. +/*!
  1158. +    \since 4.8
  1159. +
  1160. +    Returns a reference to a substring that contains the \a n rightmost characters
  1161. +    of the string.
  1162. +
  1163. +    The entire string is returned if \a n is greater than size() or
  1164. +    less than zero.
  1165. +
  1166. +    \sa leftRef(), midRef(), endsWith()
  1167. +*/
  1168. +QStringRef QStringRef::rightRef(int n) const
  1169. +{
  1170. +    if (n >= m_size || n < 0 || !m_string)
  1171. +        return *this;
  1172. +    return QStringRef(m_string, m_position + m_size - n, n);
  1173. +}
  1174. +
  1175. +/*!
  1176. +    \since 4.8
  1177. +
  1178. +    Returns a reference to a substring that contains \a n characters of this
  1179. +    string, starting at the specified \a position index.
  1180. +
  1181. +    Returns a null string if the \a position index exceeds the
  1182. +    length of the string. If there are less than \a n characters
  1183. +    available in the string starting at the given \a position, or if
  1184. +    \a n is -1 (default), the function returns all characters that
  1185. +    are available from the specified \a position.
  1186. +
  1187. +    \sa leftRef(), rightRef()
  1188. +*/
  1189. +QStringRef QStringRef::midRef(int position, int n) const
  1190. +{
  1191. +    if (position >= m_size || !m_size || !m_string)
  1192. +        return QStringRef();
  1193. +    if (n < 0)
  1194. +        n = m_size - position;
  1195. +    if (position < 0) {
  1196. +        n += position;
  1197. +        position = 0;
  1198. +    }
  1199. +    if (n + position > m_size)
  1200. +        n = m_size - position;
  1201. +    return QStringRef(m_string, m_position + position, n);
  1202. +}
  1203. +
  1204. +/*!
  1205. +    \since 4.8
  1206. +
  1207. +    Returns a reference to a substring that has whitespace removed from the
  1208. +    start and the end.
  1209. +
  1210. +    Whitespace means any character for which QChar::isSpace() returns
  1211. +    true. This includes the ASCII characters '\\t', '\\n', '\\v',
  1212. +    '\\f', '\\r', and ' '.
  1213. +
  1214. +    Unlike simplified(), trimmed() and trimmedRef() leave internal whitespace
  1215. +    alone.
  1216. +
  1217. +    \sa simplified(), trimmed()
  1218. +*/
  1219. +QStringRef QStringRef::trimmedRef() const
  1220. +{
  1221. +    if (!m_string || m_size == 0)
  1222. +        return QStringRef();
  1223. +    // skip whitespace chars from the start
  1224. +    int start = 0;
  1225. +    int end = m_size - 1;
  1226. +    while (start < m_size && at(start).isSpace())
  1227. +        ++start;
  1228. +    if (start <= m_size) {
  1229. +        while (end && at(end).isSpace())
  1230. +            --end;
  1231. +    }
  1232. +    return QStringRef(m_string, m_position + start, end - start + 1);
  1233. +}
  1234. +
  1235. +
  1236. +/*!
  1237. +    \since 4.8
  1238. +
  1239. +    Truncates the string at the given \a position index.
  1240. +
  1241. +    Essentially for QStringRef this just sets the size of the string.
  1242. +
  1243. +    If the specified \a position index is beyond the end of the
  1244. +    string, nothing happens.
  1245. +
  1246. +    If \a position is negative, it is equivalent to passing zero.
  1247. +
  1248. +    \sa chop(), leftRef()
  1249. +*/
  1250. +void QStringRef::truncate(int pos)
  1251. +{
  1252. +    if (!m_string || pos >= m_size || pos < 0)
  1253. +        return;
  1254. +    m_size = pos;
  1255. +}
  1256. +
  1257. +/*!
  1258. +    \since 4.8
  1259. +
  1260. +    Removes \a n characters from the end of the string.
  1261. +
  1262. +    Essentially for QStringRef this just sets the size of the string.
  1263. +
  1264. +    If \a n is greater than size(), the result is an empty string.
  1265. +
  1266. +    If you want to remove characters from the \e beginning of the
  1267. +    string, just create a new QStringRef.
  1268. +
  1269. +    \sa truncate()
  1270. +*/
  1271. +void QStringRef::chop(int n)
  1272. +{
  1273. +    if (!m_string || n > m_size || n < 0)
  1274. +        return;
  1275. +    m_size -= n;
  1276. +}
  1277. +
  1278.  QT_END_NAMESPACE
  1279. diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h
  1280. index 589fdc2..bebff92 100644
  1281. --- a/src/corelib/tools/qstring.h
  1282. +++ b/src/corelib/tools/qstring.h
  1283. @@ -257,11 +257,13 @@ public:
  1284.      QString toCaseFolded() const Q_REQUIRED_RESULT;
  1285.  
  1286.      QString trimmed() const Q_REQUIRED_RESULT;
  1287. +    QStringRef trimmedRef() const Q_REQUIRED_RESULT;
  1288.      QString simplified() const Q_REQUIRED_RESULT;
  1289.  
  1290.      QString &insert(int i, QChar c);
  1291.      QString &insert(int i, const QChar *uc, int len);
  1292.      inline QString &insert(int i, const QString &s) { return insert(i, s.constData(), s.length()); }
  1293. +    inline QString &insert(int i, const QStringRef &s);
  1294.      QString &insert(int i, const QLatin1String &s);
  1295.      QString &append(QChar c);
  1296.      QString &append(const QString &s);
  1297. @@ -269,6 +271,7 @@ public:
  1298.      QString &append(const QLatin1String &s);
  1299.      inline QString &prepend(QChar c) { return insert(0, c); }
  1300.      inline QString &prepend(const QString &s) { return insert(0, s); }
  1301. +    inline QString &prepend(const QStringRef &s) { return insert(0, s); }
  1302.      inline QString &prepend(const QLatin1String &s) { return insert(0, s); }
  1303.  
  1304.      inline QString &operator+=(QChar c) {
  1305. @@ -287,6 +290,7 @@ public:
  1306.      QString &remove(int i, int len);
  1307.      QString &remove(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive);
  1308.      QString &remove(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive);
  1309. +    QString &remove(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive);
  1310.      QString &replace(int i, int len, QChar after);
  1311.      QString &replace(int i, int len, const QChar *s, int slen);
  1312.      QString &replace(int i, int len, const QString &after);
  1313. @@ -309,10 +313,24 @@ public:
  1314.  
  1315.      QStringList split(const QString &sep, SplitBehavior behavior = KeepEmptyParts,
  1316.                        Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_REQUIRED_RESULT;
  1317. +    QStringList split(const QStringRef &sep, SplitBehavior behavior = KeepEmptyParts,
  1318. +                      Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_REQUIRED_RESULT;
  1319. +    QStringList split(const QLatin1String &sep, SplitBehavior behavior = KeepEmptyParts,
  1320. +                      Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_REQUIRED_RESULT;
  1321.      QStringList split(const QChar &sep, SplitBehavior behavior = KeepEmptyParts,
  1322.                        Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_REQUIRED_RESULT;
  1323. +
  1324. +    QList<QStringRef> splitRef(const QString &sep, SplitBehavior behavior = KeepEmptyParts,
  1325. +                      Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_REQUIRED_RESULT;
  1326. +    QList<QStringRef> splitRef(const QStringRef &sep, SplitBehavior behavior = KeepEmptyParts,
  1327. +                      Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_REQUIRED_RESULT;
  1328. +    QList<QStringRef> splitRef(const QLatin1String &sep, SplitBehavior behavior = KeepEmptyParts,
  1329. +                      Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_REQUIRED_RESULT;
  1330. +    QList<QStringRef> splitRef(const QChar &sep, SplitBehavior behavior = KeepEmptyParts,
  1331. +                      Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_REQUIRED_RESULT;
  1332.  #ifndef QT_NO_REGEXP
  1333.      QStringList split(const QRegExp &sep, SplitBehavior behavior = KeepEmptyParts) const Q_REQUIRED_RESULT;
  1334. +    QList<QStringRef> splitRef(const QRegExp &sep, SplitBehavior behavior = KeepEmptyParts) const Q_REQUIRED_RESULT;
  1335.  #endif
  1336.  
  1337.      enum NormalizationForm {
  1338. @@ -1136,6 +1154,15 @@ public:
  1339.      int lastIndexOf(QLatin1String str, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
  1340.      int lastIndexOf(const QStringRef &str, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
  1341.  
  1342. +    QList<QStringRef> splitRef(const QString &sep, QString::SplitBehavior behavior = QString::KeepEmptyParts,
  1343. +                      Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_REQUIRED_RESULT;
  1344. +    QList<QStringRef> splitRef(const QStringRef &sep, QString::SplitBehavior behavior = QString::KeepEmptyParts,
  1345. +                      Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_REQUIRED_RESULT;
  1346. +    QList<QStringRef> splitRef(const QLatin1String &sep, QString::SplitBehavior behavior = QString::KeepEmptyParts,
  1347. +                      Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_REQUIRED_RESULT;
  1348. +    QList<QStringRef> splitRef(const QChar &sep, QString::SplitBehavior behavior = QString::KeepEmptyParts,
  1349. +                      Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_REQUIRED_RESULT;
  1350. +
  1351.      inline QBool contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
  1352.      inline QBool contains(QChar ch, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
  1353.      inline QBool contains(QLatin1String str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
  1354. @@ -1195,13 +1222,34 @@ public:
  1355.      int localeAwareCompare(const QStringRef &s) const;
  1356.      static int localeAwareCompare(const QStringRef &s1, const QString &s2);
  1357.      static int localeAwareCompare(const QStringRef &s1, const QStringRef &s2);
  1358. +
  1359. +    short toShort(bool *ok=0, int base=10) const;
  1360. +    ushort toUShort(bool *ok=0, int base=10) const;
  1361. +    int toInt(bool *ok=0, int base=10) const;
  1362. +    uint toUInt(bool *ok=0, int base=10) const;
  1363. +    long toLong(bool *ok=0, int base=10) const;
  1364. +    ulong toULong(bool *ok=0, int base=10) const;
  1365. +    qlonglong toLongLong(bool *ok=0, int base=10) const;
  1366. +    qulonglong toULongLong(bool *ok=0, int base=10) const;
  1367. +    float toFloat(bool *ok=0) const;
  1368. +    double toDouble(bool *ok=0) const;
  1369. +
  1370. +    QStringRef leftRef(int n) const Q_REQUIRED_RESULT;
  1371. +    QStringRef rightRef(int n) const Q_REQUIRED_RESULT;
  1372. +    QStringRef midRef(int position, int n = -1) const Q_REQUIRED_RESULT;
  1373. +    QStringRef trimmedRef() const;
  1374. +    void truncate(int pos);
  1375. +    void chop(int n);
  1376.  };
  1377.  
  1378.  inline QStringRef &QStringRef::operator=(const QString *aString)
  1379.  { m_string = aString; m_position = 0; m_size = aString?aString->size():0; return *this; }
  1380.  
  1381.  inline QStringRef::QStringRef(const QString *aString, int aPosition, int aSize)
  1382. -        :m_string(aString), m_position(aPosition), m_size(aSize){}
  1383. +        :m_string(aString), m_position(aPosition), m_size(aSize)
  1384. +{
  1385. +    Q_ASSERT((!aString && aPosition == 0 && aSize == 0) || (aString && aPosition >= 0 && aSize >= 0));
  1386. +}
  1387.  
  1388.  inline QStringRef::QStringRef(const QString *aString)
  1389.      :m_string(aString), m_position(0), m_size(aString?aString->size() : 0){}
  1390. @@ -1290,6 +1338,8 @@ inline QBool QStringRef::contains(const QStringRef &s, Qt::CaseSensitivity cs) c
  1391.  
  1392.  
  1393.  
  1394. +inline QString &QString::insert(int i, const QStringRef &s) { return insert(i, s.constData(), s.length()); }
  1395. +
  1396.  QT_END_NAMESPACE
  1397.  
  1398.  QT_END_HEADER
  1399. diff --git a/src/testlib/qtest.h b/src/testlib/qtest.h
  1400. index aa9b2bd..c13c503 100644
  1401. --- a/src/testlib/qtest.h
  1402. +++ b/src/testlib/qtest.h
  1403. @@ -174,6 +174,14 @@ template<> inline char *toString(const QVariant &v)
  1404.  #ifndef QTEST_NO_SPECIALIZATIONS
  1405.  template<>
  1406.  #endif
  1407. +inline bool qCompare(QStringRef const &t1, QLatin1String const &t2, const char *actual,
  1408. +                    const char *expected, const char *file, int line)
  1409. +{
  1410. +    return qCompare<QString>(t1.toString(), QString(t2), actual, expected, file, line);
  1411. +}
  1412. +#ifndef QTEST_NO_SPECIALIZATIONS
  1413. +template<>
  1414. +#endif
  1415.  inline bool qCompare(QString const &t1, QLatin1String const &t2, const char *actual,
  1416.                      const char *expected, const char *file, int line)
  1417.  {
  1418. @@ -182,6 +190,14 @@ inline bool qCompare(QString const &t1, QLatin1String const &t2, const char *act
  1419.  #ifndef QTEST_NO_SPECIALIZATIONS
  1420.  template<>
  1421.  #endif
  1422. +inline bool qCompare(QLatin1String const &t1, QStringRef const &t2, const char *actual,
  1423. +                    const char *expected, const char *file, int line)
  1424. +{
  1425. +    return qCompare<QString>(QString(t1), t2.toString(), actual, expected, file, line);
  1426. +}
  1427. +#ifndef QTEST_NO_SPECIALIZATIONS
  1428. +template<>
  1429. +#endif
  1430.  inline bool qCompare(QLatin1String const &t1, QString const &t2, const char *actual,
  1431.                      const char *expected, const char *file, int line)
  1432.  {
  1433. diff --git a/tests/auto/qstring/tst_qstring.cpp b/tests/auto/qstring/tst_qstring.cpp
  1434. index af6b371..8050afa 100644
  1435. --- a/tests/auto/qstring/tst_qstring.cpp
  1436. +++ b/tests/auto/qstring/tst_qstring.cpp
  1437. @@ -138,6 +138,10 @@ private slots:
  1438.      void rightRef();
  1439.      void leftRef();
  1440.      void stringRef();
  1441. +    void stringRef_leftRef();
  1442. +    void stringRef_rightRef();
  1443. +    void stringRef_midRef();
  1444. +    void stringRef_trimmed();
  1445.      void contains();
  1446.      void count();
  1447.      void lastIndexOf_data();
  1448. @@ -1130,6 +1134,10 @@ void tst_QString::indexOf()
  1449.          QCOMPARE(haystack.indexOf(ref.at(0), startpos, cs), resultpos);
  1450.      }
  1451.  
  1452. +    // QStringRef overload
  1453. +    QCOMPARE( haystack.indexOf(QStringRef(&needle), startpos, cs), resultpos );
  1454. +    if (resultpos > 0 && needle.size() > 1)
  1455. +        QCOMPARE( haystack.indexOf(needle.midRef(1), startpos, cs), resultpos+1 );
  1456.  }
  1457.  
  1458.  void tst_QString::indexOf2_data()
  1459. @@ -1527,6 +1535,77 @@ void tst_QString::stringRef()
  1460.      QVERIFY(alpha == hash.value(QStringRef(&s_alpha2)));
  1461.  }
  1462.  
  1463. +void tst_QString::stringRef_leftRef()
  1464. +{
  1465. +    QString str;
  1466. +    str = QLatin1String("Foo123Bar");
  1467. +    
  1468. +    QStringRef Foo123 = str.leftRef(6);
  1469. +    QCOMPARE(Foo123, QLatin1String("Foo123"));
  1470. +    QStringRef Foo = Foo123.leftRef(3);
  1471. +    QCOMPARE(Foo, QLatin1String("Foo"));
  1472. +
  1473. +    QStringRef full = Foo123.leftRef(42);
  1474. +    QCOMPARE(full, Foo123);
  1475. +    QCOMPARE(full, QLatin1String("Foo123"));
  1476. +}
  1477. +
  1478. +void tst_QString::stringRef_rightRef()
  1479. +{
  1480. +    QString str;
  1481. +    str = QLatin1String("Foo123Bar");
  1482. +    
  1483. +    QStringRef s123Bar = str.rightRef(6);
  1484. +    QCOMPARE(s123Bar, QLatin1String("123Bar"));
  1485. +    QStringRef Bar = s123Bar.rightRef(3);
  1486. +    QCOMPARE(Bar, QLatin1String("Bar"));
  1487. +
  1488. +    QStringRef full = s123Bar.rightRef(42);
  1489. +    QCOMPARE(full, s123Bar);
  1490. +    QCOMPARE(full, QLatin1String("123Bar"));
  1491. +}
  1492. +
  1493. +void tst_QString::stringRef_midRef()
  1494. +{
  1495. +    QString str;
  1496. +    str = QLatin1String("xFoo123Barx");
  1497. +    
  1498. +    QStringRef Foo123Bar = str.midRef(1, 9);
  1499. +    QCOMPARE(Foo123Bar, QLatin1String("Foo123Bar"));
  1500. +    QStringRef s123 = Foo123Bar.midRef(3, 3);
  1501. +    QCOMPARE(s123, QLatin1String("123"));
  1502. +    QStringRef s2 = s123.midRef(1, 1);
  1503. +    QCOMPARE(s2, QLatin1String("2"));
  1504. +    QStringRef invalid = s2.midRef(10, 1);
  1505. +    QVERIFY(invalid.isNull());
  1506. +
  1507. +    QCOMPARE(Foo123Bar.midRef(3), QLatin1String("123Bar"));
  1508. +}
  1509. +
  1510. +void tst_QString::stringRef_trimmed()
  1511. +{
  1512. +    QString str;
  1513. +
  1514. +    str = QLatin1String("Text");
  1515. +    QCOMPARE(QStringRef(&str, 0, 4).toString(), QLatin1String("Text"));
  1516. +    QCOMPARE(QStringRef(&str, 0, 4).trimmed().toString(), QLatin1String("Text"));
  1517. +    QCOMPARE(QStringRef(&str, 1, 2).trimmed().toString(), QLatin1String("ex"));
  1518. +
  1519. +    str = QLatin1String(" ");
  1520. +    QCOMPARE(QStringRef(&str, 0, 1).trimmed().toString(), QLatin1String(""));
  1521. +    QCOMPARE(str, QLatin1String(" "));
  1522. +
  1523. +    str = " a   ";
  1524. +    QCOMPARE(QStringRef(&str, 0, 5).trimmed().toString(), QLatin1String("a"));
  1525. +
  1526. +    str = " abc   ";
  1527. +    QCOMPARE(QStringRef(&str, 0, 4).trimmed().toString(), QLatin1String("abc"));
  1528. +    QCOMPARE(QStringRef(&str, 1, 4).trimmed().toString(), QLatin1String("abc"));
  1529. +    QCOMPARE(QStringRef(&str, 0, 5).trimmed().toString(), QLatin1String("abc"));
  1530. +}
  1531. +
  1532. +
  1533. +
  1534.  void tst_QString::leftJustified()
  1535.  {
  1536.      QString a;
  1537. @@ -3813,7 +3892,6 @@ void tst_QString::section()
  1538.      }
  1539.  }
  1540.  
  1541. -
  1542.  void tst_QString::operator_eqeq_nullstring()
  1543.  {
  1544.      /* Some of these might not be all that logical but it's the behaviour we've had since 3.0.0
  1545. --
  1546. 1.7.1
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement