summaryrefslogtreecommitdiffstats
path: root/src/corelib/io/qurl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/io/qurl.cpp')
-rw-r--r--src/corelib/io/qurl.cpp555
1 files changed, 259 insertions, 296 deletions
diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp
index 1e74b2ad9f..4360b5b076 100644
--- a/src/corelib/io/qurl.cpp
+++ b/src/corelib/io/qurl.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
/*!
\class QUrl
@@ -50,14 +14,18 @@
\ingroup network
\ingroup shared
+ \compares weak
It can parse and construct URLs in both encoded and unencoded
form. QUrl also has support for internationalized domain names
(IDNs).
- The most common way to use QUrl is to initialize it via the
- constructor by passing a QString. Otherwise, setUrl() can also
- be used.
+ The most common way to use QUrl is to initialize it via the constructor by
+ passing a QString containing a full URL. QUrl objects can also be created
+ from a QByteArray containing a full URL using QUrl::fromEncoded(), or
+ heuristically from incomplete URLs using QUrl::fromUserInput(). The URL
+ representation can be obtained from a QUrl using either QUrl::toString() or
+ QUrl::toEncoded().
URLs can be represented in two forms: encoded or unencoded. The
unencoded representation is suitable for showing to users, but
@@ -436,16 +404,17 @@
#include "private/qipaddress_p.h"
#include "qurlquery.h"
#include "private/qdir_p.h"
+#include <private/qtools_p.h>
QT_BEGIN_NAMESPACE
-// in qstring.cpp:
-void qt_from_latin1(char16_t *dst, const char *str, size_t size) noexcept;
+using namespace Qt::StringLiterals;
+using namespace QtMiscUtils;
inline static bool isHex(char c)
{
c |= 0x20;
- return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f');
+ return isAsciiDigit(c) || (c >= 'a' && c <= 'f');
}
static inline QString ftpScheme()
@@ -526,8 +495,8 @@ public:
struct Error {
QString source;
+ qsizetype position;
ErrorCode code;
- int position;
};
QUrlPrivate();
@@ -540,11 +509,11 @@ public:
std::unique_ptr<Error> cloneError() const;
void clearError();
- void setError(ErrorCode errorCode, const QString &source, int supplement = -1);
- ErrorCode validityError(QString *source = nullptr, int *position = nullptr) const;
- bool validateComponent(Section section, const QString &input, int begin, int end);
+ void setError(ErrorCode errorCode, const QString &source, qsizetype supplement = -1);
+ ErrorCode validityError(QString *source = nullptr, qsizetype *position = nullptr) const;
+ bool validateComponent(Section section, const QString &input, qsizetype begin, qsizetype end);
bool validateComponent(Section section, const QString &input)
- { return validateComponent(section, input, 0, uint(input.length())); }
+ { return validateComponent(section, input, 0, input.size()); }
// no QString scheme() const;
void appendAuthority(QString &appendTo, QUrl::FormattingOptions options, Section appendingTo) const;
@@ -557,15 +526,15 @@ public:
void appendFragment(QString &appendTo, QUrl::FormattingOptions options, Section appendingTo) const;
// the "end" parameters are like STL iterators: they point to one past the last valid element
- bool setScheme(const QString &value, int len, bool doSetError);
- void setAuthority(const QString &auth, int from, int end, QUrl::ParsingMode mode);
- void setUserInfo(const QString &userInfo, int from, int end);
- void setUserName(const QString &value, int from, int end);
- void setPassword(const QString &value, int from, int end);
- bool setHost(const QString &value, int from, int end, QUrl::ParsingMode mode);
- void setPath(const QString &value, int from, int end);
- void setQuery(const QString &value, int from, int end);
- void setFragment(const QString &value, int from, int end);
+ bool setScheme(const QString &value, qsizetype len, bool doSetError);
+ void setAuthority(const QString &auth, qsizetype from, qsizetype end, QUrl::ParsingMode mode);
+ void setUserInfo(const QString &userInfo, qsizetype from, qsizetype end);
+ void setUserName(const QString &value, qsizetype from, qsizetype end);
+ void setPassword(const QString &value, qsizetype from, qsizetype end);
+ bool setHost(const QString &value, qsizetype from, qsizetype end, QUrl::ParsingMode mode);
+ void setPath(const QString &value, qsizetype from, qsizetype end);
+ void setQuery(const QString &value, qsizetype from, qsizetype end);
+ void setFragment(const QString &value, qsizetype from, qsizetype end);
inline bool hasScheme() const { return sectionIsPresent & Scheme; }
inline bool hasAuthority() const { return sectionIsPresent & Authority; }
@@ -642,7 +611,7 @@ inline void QUrlPrivate::clearError()
error.reset();
}
-inline void QUrlPrivate::setError(ErrorCode errorCode, const QString &source, int supplement)
+inline void QUrlPrivate::setError(ErrorCode errorCode, const QString &source, qsizetype supplement)
{
if (error) {
// don't overwrite an error set in a previous section during parsing
@@ -833,11 +802,11 @@ static const ushort * const fragmentInUrl = userNameInUrl + 6;
static inline void parseDecodedComponent(QString &data)
{
- data.replace(QLatin1Char('%'), QLatin1String("%25"));
+ data.replace(u'%', "%25"_L1);
}
static inline QString
-recodeFromUser(const QString &input, const ushort *actions, int from, int to)
+recodeFromUser(const QString &input, const ushort *actions, qsizetype from, qsizetype to)
{
QString output;
const QChar *begin = input.constData() + from;
@@ -853,14 +822,16 @@ recodeFromUser(const QString &input, const ushort *actions, int from, int to)
static inline void appendToUser(QString &appendTo, QStringView value, QUrl::FormattingOptions options,
const ushort *actions)
{
- // Test ComponentFormattingOptions, ignore FormattingOptions.
- if ((options & 0xFFFF0000) == QUrl::PrettyDecoded) {
+ // The stored value is already QUrl::PrettyDecoded, so there's nothing to
+ // do if that's what the user asked for (test only
+ // ComponentFormattingOptions, ignore FormattingOptions).
+ if ((options & 0xFFFF0000) == QUrl::PrettyDecoded ||
+ !qt_urlRecode(appendTo, value, options, actions))
appendTo += value;
- return;
- }
- if (!qt_urlRecode(appendTo, value, options, actions))
- appendTo += value;
+ // copy nullness, if necessary, because QString::operator+=(QStringView) doesn't
+ if (appendTo.isNull() && !value.isNull())
+ appendTo.detach();
}
inline void QUrlPrivate::appendAuthority(QString &appendTo, QUrl::FormattingOptions options, Section appendingTo) const
@@ -870,11 +841,11 @@ inline void QUrlPrivate::appendAuthority(QString &appendTo, QUrl::FormattingOpti
// add '@' only if we added anything
if (hasUserName() || (hasPassword() && (options & QUrl::RemovePassword) == 0))
- appendTo += QLatin1Char('@');
+ appendTo += u'@';
}
appendHost(appendTo, options);
if (!(options & QUrl::RemovePort) && port != -1)
- appendTo += QLatin1Char(':') + QString::number(port);
+ appendTo += u':' + QString::number(port);
}
inline void QUrlPrivate::appendUserInfo(QString &appendTo, QUrl::FormattingOptions options, Section appendingTo) const
@@ -916,7 +887,7 @@ inline void QUrlPrivate::appendUserInfo(QString &appendTo, QUrl::FormattingOptio
if (options & QUrl::RemovePassword || !hasPassword()) {
return;
} else {
- appendTo += QLatin1Char(':');
+ appendTo += u':';
if (!qt_urlRecode(appendTo, password, options, passwordActions))
appendTo += password;
}
@@ -945,14 +916,14 @@ inline void QUrlPrivate::appendPath(QString &appendTo, QUrl::FormattingOptions o
QStringView thePathView(thePath);
if (options & QUrl::RemoveFilename) {
- const int slash = path.lastIndexOf(QLatin1Char('/'));
+ const qsizetype slash = path.lastIndexOf(u'/');
if (slash == -1)
return;
thePathView = QStringView{path}.left(slash + 1);
}
// check if we need to remove trailing slashes
if (options & QUrl::StripTrailingSlash) {
- while (thePathView.length() > 1 && thePathView.endsWith(QLatin1Char('/')))
+ while (thePathView.size() > 1 && thePathView.endsWith(u'/'))
thePathView.chop(1);
}
@@ -975,7 +946,7 @@ inline void QUrlPrivate::appendQuery(QString &appendTo, QUrl::FormattingOptions
// setXXX functions
-inline bool QUrlPrivate::setScheme(const QString &value, int len, bool doSetError)
+inline bool QUrlPrivate::setScheme(const QString &value, qsizetype len, bool doSetError)
{
// schemes are strictly RFC-compliant:
// scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
@@ -991,17 +962,17 @@ inline bool QUrlPrivate::setScheme(const QString &value, int len, bool doSetErro
sectionIsPresent |= Scheme;
// validate it:
- int needsLowercasing = -1;
- const ushort *p = value.utf16();
- for (int i = 0; i < len; ++i) {
- if (p[i] >= 'a' && p[i] <= 'z')
+ qsizetype needsLowercasing = -1;
+ const ushort *p = reinterpret_cast<const ushort *>(value.data());
+ for (qsizetype i = 0; i < len; ++i) {
+ if (isAsciiLower(p[i]))
continue;
- if (p[i] >= 'A' && p[i] <= 'Z') {
+ if (isAsciiUpper(p[i])) {
needsLowercasing = i;
continue;
}
if (i) {
- if (p[i] >= '0' && p[i] <= '9')
+ if (isAsciiDigit(p[i]))
continue;
if (p[i] == '+' || p[i] == '-' || p[i] == '.')
continue;
@@ -1020,9 +991,9 @@ inline bool QUrlPrivate::setScheme(const QString &value, int len, bool doSetErro
if (needsLowercasing != -1) {
// schemes are ASCII only, so we don't need the full Unicode toLower
QChar *schemeData = scheme.data(); // force detaching here
- for (int i = needsLowercasing; i >= 0; --i) {
+ for (qsizetype i = needsLowercasing; i >= 0; --i) {
ushort c = schemeData[i].unicode();
- if (c >= 'A' && c <= 'Z')
+ if (isAsciiUpper(c))
schemeData[i] = QChar(c + 0x20);
}
}
@@ -1040,7 +1011,7 @@ inline bool QUrlPrivate::setScheme(const QString &value, int len, bool doSetErro
return true;
}
-inline void QUrlPrivate::setAuthority(const QString &auth, int from, int end, QUrl::ParsingMode mode)
+inline void QUrlPrivate::setAuthority(const QString &auth, qsizetype from, qsizetype end, QUrl::ParsingMode mode)
{
sectionIsPresent &= ~Authority;
sectionIsPresent |= Host;
@@ -1048,33 +1019,33 @@ inline void QUrlPrivate::setAuthority(const QString &auth, int from, int end, QU
// we never actually _loop_
while (from != end) {
- int userInfoIndex = auth.indexOf(QLatin1Char('@'), from);
- if (uint(userInfoIndex) < uint(end)) {
+ qsizetype userInfoIndex = auth.indexOf(u'@', from);
+ if (size_t(userInfoIndex) < size_t(end)) {
setUserInfo(auth, from, userInfoIndex);
if (mode == QUrl::StrictMode && !validateComponent(UserInfo, auth, from, userInfoIndex))
break;
from = userInfoIndex + 1;
}
- int colonIndex = auth.lastIndexOf(QLatin1Char(':'), end - 1);
+ qsizetype colonIndex = auth.lastIndexOf(u':', end - 1);
if (colonIndex < from)
colonIndex = -1;
- if (uint(colonIndex) < uint(end)) {
+ if (size_t(colonIndex) < size_t(end)) {
if (auth.at(from).unicode() == '[') {
// check if colonIndex isn't inside the "[...]" part
- int closingBracket = auth.indexOf(QLatin1Char(']'), from);
- if (uint(closingBracket) > uint(colonIndex))
+ qsizetype closingBracket = auth.indexOf(u']', from);
+ if (size_t(closingBracket) > size_t(colonIndex))
colonIndex = -1;
}
}
- if (uint(colonIndex) < uint(end) - 1) {
+ if (size_t(colonIndex) < size_t(end) - 1) {
// found a colon with digits after it
unsigned long x = 0;
- for (int i = colonIndex + 1; i < end; ++i) {
+ for (qsizetype i = colonIndex + 1; i < end; ++i) {
ushort c = auth.at(i).unicode();
- if (c >= '0' && c <= '9') {
+ if (isAsciiDigit(c)) {
x *= 10;
x += c - '0';
} else {
@@ -1091,8 +1062,8 @@ inline void QUrlPrivate::setAuthority(const QString &auth, int from, int end, QU
}
}
- setHost(auth, from, qMin<uint>(end, colonIndex), mode);
- if (mode == QUrl::StrictMode && !validateComponent(Host, auth, from, qMin<uint>(end, colonIndex))) {
+ setHost(auth, from, qMin<size_t>(end, colonIndex), mode);
+ if (mode == QUrl::StrictMode && !validateComponent(Host, auth, from, qMin<size_t>(end, colonIndex))) {
// clear host too
sectionIsPresent &= ~Authority;
break;
@@ -1109,12 +1080,12 @@ inline void QUrlPrivate::setAuthority(const QString &auth, int from, int end, QU
port = -1;
}
-inline void QUrlPrivate::setUserInfo(const QString &userInfo, int from, int end)
+inline void QUrlPrivate::setUserInfo(const QString &userInfo, qsizetype from, qsizetype end)
{
- int delimIndex = userInfo.indexOf(QLatin1Char(':'), from);
- setUserName(userInfo, from, qMin<uint>(delimIndex, end));
+ qsizetype delimIndex = userInfo.indexOf(u':', from);
+ setUserName(userInfo, from, qMin<size_t>(delimIndex, end));
- if (uint(delimIndex) >= uint(end)) {
+ if (size_t(delimIndex) >= size_t(end)) {
password.clear();
sectionIsPresent &= ~Password;
} else {
@@ -1122,31 +1093,31 @@ inline void QUrlPrivate::setUserInfo(const QString &userInfo, int from, int end)
}
}
-inline void QUrlPrivate::setUserName(const QString &value, int from, int end)
+inline void QUrlPrivate::setUserName(const QString &value, qsizetype from, qsizetype end)
{
sectionIsPresent |= UserName;
userName = recodeFromUser(value, userNameInIsolation, from, end);
}
-inline void QUrlPrivate::setPassword(const QString &value, int from, int end)
+inline void QUrlPrivate::setPassword(const QString &value, qsizetype from, qsizetype end)
{
sectionIsPresent |= Password;
password = recodeFromUser(value, passwordInIsolation, from, end);
}
-inline void QUrlPrivate::setPath(const QString &value, int from, int end)
+inline void QUrlPrivate::setPath(const QString &value, qsizetype from, qsizetype end)
{
// sectionIsPresent |= Path; // not used, save some cycles
path = recodeFromUser(value, pathInIsolation, from, end);
}
-inline void QUrlPrivate::setFragment(const QString &value, int from, int end)
+inline void QUrlPrivate::setFragment(const QString &value, qsizetype from, qsizetype end)
{
sectionIsPresent |= Fragment;
fragment = recodeFromUser(value, fragmentInIsolation, from, end);
}
-inline void QUrlPrivate::setQuery(const QString &value, int from, int iend)
+inline void QUrlPrivate::setQuery(const QString &value, qsizetype from, qsizetype iend)
{
sectionIsPresent |= Query;
query = recodeFromUser(value, queryInIsolation, from, iend);
@@ -1216,16 +1187,14 @@ static const QChar *parseIpFuture(QString &host, const QChar *begin, const QChar
const QChar *const origBegin = begin;
if (begin[3].unicode() != '.')
return &begin[3];
- if ((begin[2].unicode() >= 'A' && begin[2].unicode() <= 'F') ||
- (begin[2].unicode() >= 'a' && begin[2].unicode() <= 'f') ||
- (begin[2].unicode() >= '0' && begin[2].unicode() <= '9')) {
+ if (isHexDigit(begin[2].unicode())) {
// this is so unlikely that we'll just go down the slow path
// decode the whole string, skipping the "[vH." and "]" which we already know to be there
host += QStringView(begin, 4);
// uppercase the version, if necessary
if (begin[2].unicode() >= 'a')
- host[host.length() - 2] = QChar{begin[2].unicode() - 0x20};
+ host[host.size() - 2] = QChar{begin[2].unicode() - 0x20};
begin += 4;
--end;
@@ -1237,18 +1206,14 @@ static const QChar *parseIpFuture(QString &host, const QChar *begin, const QChar
}
for ( ; begin != end; ++begin) {
- if (begin->unicode() >= 'A' && begin->unicode() <= 'Z')
- host += *begin;
- else if (begin->unicode() >= 'a' && begin->unicode() <= 'z')
- host += *begin;
- else if (begin->unicode() >= '0' && begin->unicode() <= '9')
+ if (isAsciiLetterOrNumber(begin->unicode()))
host += *begin;
else if (begin->unicode() < 0x80 && strchr(acceptable, begin->unicode()) != nullptr)
host += *begin;
else
return decoded.isEmpty() ? begin : &origBegin[2];
}
- host += QLatin1Char(']');
+ host += u']';
return nullptr;
}
return &origBegin[2];
@@ -1270,7 +1235,7 @@ static const QChar *parseIp6(QString &host, const QChar *begin, const QChar *end
QIPAddressUtils::IPv6Address address;
QStringView zoneId;
- int zoneIdPosition = decoded.indexOf(zoneIdIdentifier);
+ qsizetype zoneIdPosition = decoded.indexOf(zoneIdIdentifier);
if ((zoneIdPosition != -1) && (decoded.lastIndexOf(zoneIdIdentifier) == zoneIdPosition)) {
zoneId = decoded.mid(zoneIdPosition + zoneIdIdentifier.size());
decoded.truncate(zoneIdPosition);
@@ -1290,23 +1255,24 @@ static const QChar *parseIp6(QString &host, const QChar *begin, const QChar *end
return begin + (ret - decoded.constBegin());
host.reserve(host.size() + (end - begin) + 2); // +2 for the brackets
- host += QLatin1Char('[');
+ host += u'[';
QIPAddressUtils::toString(host, address);
if (!zoneId.isEmpty()) {
host += zoneIdIdentifier;
host += zoneId;
}
- host += QLatin1Char(']');
+ host += u']';
return nullptr;
}
-inline bool QUrlPrivate::setHost(const QString &value, int from, int iend, QUrl::ParsingMode mode)
+inline bool
+QUrlPrivate::setHost(const QString &value, qsizetype from, qsizetype iend, QUrl::ParsingMode mode)
{
const QChar *begin = value.constData() + from;
const QChar *end = value.constData() + iend;
- const int len = end - begin;
+ const qsizetype len = end - begin;
host.clear();
sectionIsPresent |= Host;
if (len == 0)
@@ -1367,14 +1333,14 @@ inline bool QUrlPrivate::setHost(const QString &value, int from, int iend, QUrl:
if (mode == QUrl::TolerantMode && qt_urlRecode(s, QStringView{begin, end}, { }, nullptr)) {
// something was decoded
// anything encoded left?
- int pos = s.indexOf(QChar(0x25)); // '%'
+ qsizetype pos = s.indexOf(QChar(0x25)); // '%'
if (pos != -1) {
setError(InvalidRegNameError, s, pos);
return false;
}
// recurse
- return setHost(s, 0, s.length(), QUrl::StrictMode);
+ return setHost(s, 0, s.size(), QUrl::StrictMode);
}
s = qt_ACE_do(value.mid(from, iend - from), NormalizeAce, ForbidLeadingDot, {});
@@ -1407,15 +1373,15 @@ inline void QUrlPrivate::parse(const QString &url, QUrl::ParsingMode parsingMode
clearError();
// find the important delimiters
- int colon = -1;
- int question = -1;
- int hash = -1;
- const int len = url.length();
+ qsizetype colon = -1;
+ qsizetype question = -1;
+ qsizetype hash = -1;
+ const qsizetype len = url.size();
const QChar *const begin = url.constData();
const ushort *const data = reinterpret_cast<const ushort *>(begin);
- for (int i = 0; i < len; ++i) {
- uint uc = data[i];
+ for (qsizetype i = 0; i < len; ++i) {
+ size_t uc = data[i];
if (uc == '#' && hash == -1) {
hash = i;
@@ -1432,7 +1398,7 @@ inline void QUrlPrivate::parse(const QString &url, QUrl::ParsingMode parsingMode
}
// check if we have a scheme
- int hierStart;
+ qsizetype hierStart;
if (colon != -1 && setScheme(url, colon, /* don't set error */ false)) {
hierStart = colon + 1;
} else {
@@ -1442,12 +1408,12 @@ inline void QUrlPrivate::parse(const QString &url, QUrl::ParsingMode parsingMode
hierStart = 0;
}
- int pathStart;
- int hierEnd = qMin<uint>(qMin<uint>(question, hash), len);
+ qsizetype pathStart;
+ qsizetype hierEnd = qMin<size_t>(qMin<size_t>(question, hash), len);
if (hierEnd - hierStart >= 2 && data[hierStart] == '/' && data[hierStart + 1] == '/') {
// we have an authority, it ends at the first slash after these
- int authorityEnd = hierEnd;
- for (int i = hierStart + 2; i < authorityEnd ; ++i) {
+ qsizetype authorityEnd = hierEnd;
+ for (qsizetype i = hierStart + 2; i < authorityEnd ; ++i) {
if (data[i] == '/') {
authorityEnd = i;
break;
@@ -1472,8 +1438,8 @@ inline void QUrlPrivate::parse(const QString &url, QUrl::ParsingMode parsingMode
path.clear();
}
- if (uint(question) < uint(hash))
- setQuery(url, question + 1, qMin<uint>(hash, len));
+ if (size_t(question) < size_t(hash))
+ setQuery(url, question + 1, qMin<size_t>(hash, len));
if (hash != -1)
setFragment(url, hash + 1, len);
@@ -1489,7 +1455,7 @@ inline void QUrlPrivate::parse(const QString &url, QUrl::ParsingMode parsingMode
if (!validateComponent(Path, url, pathStart, hierEnd))
return;
- if (uint(question) < uint(hash) && !validateComponent(Query, url, question + 1, qMin<uint>(hash, len)))
+ if (size_t(question) < size_t(hash) && !validateComponent(Query, url, question + 1, qMin<size_t>(hash, len)))
return;
if (hash != -1)
validateComponent(Fragment, url, hash + 1, len);
@@ -1503,19 +1469,19 @@ QString QUrlPrivate::toLocalFile(QUrl::FormattingOptions options) const
// magic for shared drive on windows
if (!host.isEmpty()) {
- tmp = QLatin1String("//") + host;
+ tmp = "//"_L1 + host;
#ifdef Q_OS_WIN // QTBUG-42346, WebDAV is visible as local file on Windows only.
if (scheme == webDavScheme())
tmp += webDavSslTag();
#endif
- if (!ourPath.isEmpty() && !ourPath.startsWith(QLatin1Char('/')))
- tmp += QLatin1Char('/');
+ if (!ourPath.isEmpty() && !ourPath.startsWith(u'/'))
+ tmp += u'/';
tmp += ourPath;
} else {
tmp = ourPath;
#ifdef Q_OS_WIN
// magic for drives on windows
- if (ourPath.length() > 2 && ourPath.at(0) == QLatin1Char('/') && ourPath.at(2) == QLatin1Char(':'))
+ if (ourPath.length() > 2 && ourPath.at(0) == u'/' && ourPath.at(2) == u':')
tmp.remove(0, 1);
#endif
}
@@ -1536,7 +1502,7 @@ inline QString QUrlPrivate::mergePaths(const QString &relativePath) const
// path, then return a string consisting of "/" concatenated with
// the reference's path; otherwise,
if (!host.isEmpty() && path.isEmpty())
- return QLatin1Char('/') + relativePath;
+ return u'/' + relativePath;
// Return a string consisting of the reference's path component
// appended to all but the last segment of the base URI's path
@@ -1544,10 +1510,10 @@ inline QString QUrlPrivate::mergePaths(const QString &relativePath) const
// base URI path, or excluding the entire base URI path if it does
// not contain any "/" characters).
QString newPath;
- if (!path.contains(QLatin1Char('/')))
+ if (!path.contains(u'/'))
newPath = relativePath;
else
- newPath = QStringView{path}.left(path.lastIndexOf(QLatin1Char('/')) + 1) + relativePath;
+ newPath = QStringView{path}.left(path.lastIndexOf(u'/') + 1) + relativePath;
return newPath;
}
@@ -1593,7 +1559,7 @@ static void removeDotsFromPath(QString *path)
in += 2;
continue;
} else if (in == end - 2 && in[0].unicode() == '/' && in[1].unicode() == '.') {
- *out++ = QLatin1Char('/');
+ *out++ = u'/';
in += 2;
break;
}
@@ -1634,7 +1600,7 @@ static void removeDotsFromPath(QString *path)
path->truncate(out - path->constData());
}
-inline QUrlPrivate::ErrorCode QUrlPrivate::validityError(QString *source, int *position) const
+inline QUrlPrivate::ErrorCode QUrlPrivate::validityError(QString *source, qsizetype *position) const
{
Q_ASSERT(!source == !position);
if (error) {
@@ -1660,8 +1626,8 @@ inline QUrlPrivate::ErrorCode QUrlPrivate::validityError(QString *source, int *p
if (path.isEmpty())
return NoError;
- if (path.at(0) == QLatin1Char('/')) {
- if (hasAuthority() || path.length() == 1 || path.at(1) != QLatin1Char('/'))
+ if (path.at(0) == u'/') {
+ if (hasAuthority() || path.size() == 1 || path.at(1) != u'/')
return NoError;
if (source) {
*source = path;
@@ -1681,7 +1647,7 @@ inline QUrlPrivate::ErrorCode QUrlPrivate::validityError(QString *source, int *p
return NoError;
// check for a path of "text:text/"
- for (int i = 0; i < path.length(); ++i) {
+ for (qsizetype i = 0; i < path.size(); ++i) {
ushort c = path.at(i).unicode();
if (c == '/') {
// found the slash before the colon
@@ -1700,7 +1666,7 @@ inline QUrlPrivate::ErrorCode QUrlPrivate::validityError(QString *source, int *p
}
bool QUrlPrivate::validateComponent(QUrlPrivate::Section section, const QString &input,
- int begin, int end)
+ qsizetype begin, qsizetype end)
{
// What we need to look out for, that the regular parser tolerates:
// - percent signs not followed by two hex digits
@@ -1721,13 +1687,13 @@ bool QUrlPrivate::validateComponent(QUrlPrivate::Section section, const QString
Q_ASSERT(section != Authority && section != Hierarchy && section != FullUrl);
const ushort *const data = reinterpret_cast<const ushort *>(input.constData());
- for (uint i = uint(begin); i < uint(end); ++i) {
+ for (size_t i = size_t(begin); i < size_t(end); ++i) {
uint uc = data[i];
if (uc >= 0x80)
continue;
bool error = false;
- if ((uc == '%' && (uint(end) < i + 2 || !isHex(data[i + 1]) || !isHex(data[i + 2])))
+ if ((uc == '%' && (size_t(end) < i + 2 || !isHex(data[i + 1]) || !isHex(data[i + 2])))
|| uc <= 0x20 || strchr(forbidden, uc)) {
// found an error
error = true;
@@ -1745,7 +1711,7 @@ bool QUrlPrivate::validateComponent(QUrlPrivate::Section section, const QString
if (section == UserInfo) {
// is it the user name or the password?
errorCode = InvalidUserNameError;
- for (uint j = uint(begin); j < i; ++j)
+ for (size_t j = size_t(begin); j < i; ++j)
if (data[j] == ':') {
errorCode = InvalidPasswordError;
break;
@@ -1778,7 +1744,7 @@ inline void QUrlPrivate::validate() const
if (!isHostValid)
return;
- if (scheme == QLatin1String("mailto")) {
+ if (scheme == "mailto"_L1) {
if (!host.isEmpty() || port != -1 || !userName.isEmpty() || !password.isEmpty()) {
that->isValid = false;
that->errorInfo.setParams(0, QT_TRANSLATE_NOOP(QUrl, "expected empty host, username,"
@@ -1825,7 +1791,20 @@ inline void QUrlPrivate::validate() const
/*!
- Constructs a URL by parsing \a url. QUrl will automatically percent encode
+ Constructs a URL by parsing \a url. Note this constructor expects a proper
+ URL or URL-Reference and will not attempt to guess intent. For example, the
+ following declaration:
+
+ \snippet code/src_corelib_io_qurl.cpp constructor-url-reference
+
+ Will construct a valid URL but it may not be what one expects, as the
+ scheme() part of the input is missing. For a string like the above,
+ applications may want to use fromUserInput(). For this constructor or
+ setUrl(), the following is probably what was intended:
+
+ \snippet code/src_corelib_io_qurl.cpp constructor-url
+
+ QUrl will automatically percent encode
all characters that are not allowed in a URL and decode the percent-encoded
sequences that represent an unreserved character (letters, digits, hyphens,
underscores, dots and tildes). All other characters are left in their
@@ -1870,7 +1849,7 @@ QUrl::QUrl() : d(nullptr)
/*!
Constructs a copy of \a other.
*/
-QUrl::QUrl(const QUrl &other) : d(other.d)
+QUrl::QUrl(const QUrl &other) noexcept : d(other.d)
{
if (d)
d->ref.ref();
@@ -1989,7 +1968,7 @@ void QUrl::setScheme(const QString &scheme)
d->flags &= ~QUrlPrivate::IsLocalFile;
d->scheme.clear();
} else {
- d->setScheme(scheme, scheme.length(), /* do set error */ true);
+ d->setScheme(scheme, scheme.size(), /* do set error */ true);
}
}
@@ -2049,7 +2028,7 @@ void QUrl::setAuthority(const QString &authority, ParsingMode mode)
return;
}
- d->setAuthority(authority, 0, authority.length(), mode);
+ d->setAuthority(authority, 0, authority.size(), mode);
if (authority.isNull()) {
// QUrlPrivate::setAuthority cleared almost everything
// but it leaves the Host bit set
@@ -2120,7 +2099,7 @@ void QUrl::setUserInfo(const QString &userInfo, ParsingMode mode)
return;
}
- d->setUserInfo(trimmed, 0, trimmed.length());
+ d->setUserInfo(trimmed, 0, trimmed.size());
if (userInfo.isNull()) {
// QUrlPrivate::setUserInfo cleared almost everything
// but it leaves the UserName bit set
@@ -2192,7 +2171,7 @@ void QUrl::setUserName(const QString &userName, ParsingMode mode)
mode = TolerantMode;
}
- d->setUserName(data, 0, data.length());
+ d->setUserName(data, 0, data.size());
if (userName.isNull())
d->sectionIsPresent &= ~QUrlPrivate::UserName;
else if (mode == StrictMode && !d->validateComponent(QUrlPrivate::UserName, userName))
@@ -2255,7 +2234,7 @@ void QUrl::setPassword(const QString &password, ParsingMode mode)
mode = TolerantMode;
}
- d->setPassword(data, 0, data.length());
+ d->setPassword(data, 0, data.size());
if (password.isNull())
d->sectionIsPresent &= ~QUrlPrivate::Password;
else if (mode == StrictMode && !d->validateComponent(QUrlPrivate::Password, password))
@@ -2317,18 +2296,18 @@ void QUrl::setHost(const QString &host, ParsingMode mode)
mode = TolerantMode;
}
- if (d->setHost(data, 0, data.length(), mode)) {
+ if (d->setHost(data, 0, data.size(), mode)) {
if (host.isNull())
d->sectionIsPresent &= ~QUrlPrivate::Host;
- } else if (!data.startsWith(QLatin1Char('['))) {
+ } else if (!data.startsWith(u'[')) {
// setHost failed, it might be IPv6 or IPvFuture in need of bracketing
Q_ASSERT(d->error);
- data.prepend(QLatin1Char('['));
- data.append(QLatin1Char(']'));
- if (!d->setHost(data, 0, data.length(), mode)) {
+ data.prepend(u'[');
+ data.append(u']');
+ if (!d->setHost(data, 0, data.size(), mode)) {
// failed again
- if (data.contains(QLatin1Char(':'))) {
+ if (data.contains(u':')) {
// source data contains ':', so it's an IPv6 error
d->error->code = QUrlPrivate::InvalidIPv6AddressError;
}
@@ -2362,8 +2341,8 @@ QString QUrl::host(ComponentFormattingOptions options) const
QString result;
if (d) {
d->appendHost(result, options);
- if (result.startsWith(QLatin1Char('[')))
- result = result.mid(1, result.length() - 2);
+ if (result.startsWith(u'['))
+ result = result.mid(1, result.size() - 2);
}
return result;
}
@@ -2442,7 +2421,7 @@ void QUrl::setPath(const QString &path, ParsingMode mode)
mode = TolerantMode;
}
- d->setPath(data, 0, data.length());
+ d->setPath(data, 0, data.size());
// optimized out, since there is no path delimiter
// if (path.isNull())
@@ -2517,7 +2496,7 @@ QString QUrl::path(ComponentFormattingOptions options) const
QString QUrl::fileName(ComponentFormattingOptions options) const
{
const QString ourPath = path(options);
- const int slash = ourPath.lastIndexOf(QLatin1Char('/'));
+ const qsizetype slash = ourPath.lastIndexOf(u'/');
if (slash == -1)
return ourPath;
return ourPath.mid(slash + 1);
@@ -2578,7 +2557,7 @@ void QUrl::setQuery(const QString &query, ParsingMode mode)
mode = TolerantMode;
}
- d->setQuery(data, 0, data.length());
+ d->setQuery(data, 0, data.size());
if (query.isNull())
d->sectionIsPresent &= ~QUrlPrivate::Query;
else if (mode == StrictMode && !d->validateComponent(QUrlPrivate::Query, query))
@@ -2676,7 +2655,7 @@ void QUrl::setFragment(const QString &fragment, ParsingMode mode)
mode = TolerantMode;
}
- d->setFragment(data, 0, data.length());
+ d->setFragment(data, 0, data.size());
if (fragment.isNull())
d->sectionIsPresent &= ~QUrlPrivate::Fragment;
else if (mode == StrictMode && !d->validateComponent(QUrlPrivate::Fragment, fragment))
@@ -2775,7 +2754,7 @@ QUrl QUrl::resolved(const QUrl &relative) const
t.d->sectionIsPresent |= QUrlPrivate::Query;
}
} else {
- t.d->path = relative.d->path.startsWith(QLatin1Char('/'))
+ t.d->path = relative.d->path.startsWith(u'/')
? relative.d->path
: d->mergePaths(relative.d->path);
if (relative.d->hasQuery()) {
@@ -2882,26 +2861,26 @@ QString QUrl::toString(FormattingOptions options) const
options |= EncodeReserved;
if (!(options & QUrl::RemoveScheme) && d->hasScheme())
- url += d->scheme + QLatin1Char(':');
+ url += d->scheme + u':';
- bool pathIsAbsolute = d->path.startsWith(QLatin1Char('/'));
+ bool pathIsAbsolute = d->path.startsWith(u'/');
if (!((options & QUrl::RemoveAuthority) == QUrl::RemoveAuthority) && d->hasAuthority()) {
- url += QLatin1String("//");
+ url += "//"_L1;
d->appendAuthority(url, options, QUrlPrivate::FullUrl);
} else if (isLocalFile() && pathIsAbsolute) {
// Comply with the XDG file URI spec, which requires triple slashes.
- url += QLatin1String("//");
+ url += "//"_L1;
}
if (!(options & QUrl::RemovePath))
d->appendPath(url, options, QUrlPrivate::FullUrl);
if (!(options & QUrl::RemoveQuery) && d->hasQuery()) {
- url += QLatin1Char('?');
+ url += u'?';
d->appendQuery(url, options, QUrlPrivate::FullUrl);
}
if (!(options & QUrl::RemoveFragment) && d->hasFragment()) {
- url += QLatin1Char('#');
+ url += u'#';
d->appendFragment(url, options, QUrlPrivate::FullUrl);
}
@@ -2970,7 +2949,7 @@ QUrl QUrl::adjusted(QUrl::FormattingOptions options) const
that.detach();
QString path;
d->appendPath(path, options | FullyEncoded, QUrlPrivate::Path);
- that.d->setPath(path, 0, path.length());
+ that.d->setPath(path, 0, path.size());
}
return that;
}
@@ -2991,19 +2970,23 @@ QByteArray QUrl::toEncoded(FormattingOptions options) const
}
/*!
- \fn QUrl QUrl::fromEncoded(const QByteArray &input, ParsingMode parsingMode)
-
Parses \a input and returns the corresponding QUrl. \a input is
assumed to be in encoded form, containing only ASCII characters.
- Parses the URL using \a parsingMode. See setUrl() for more information on
+ Parses the URL using \a mode. See setUrl() for more information on
this parameter. QUrl::DecodedMode is not permitted in this context.
+ \note In Qt versions prior to 6.7, this function took a QByteArray, not
+ QByteArrayView. If you experience compile errors, it's because your code
+ is passing objects that are implicitly convertible to QByteArray, but not
+ QByteArrayView. Wrap the corresponding argument in \c{QByteArray{~~~}} to
+ make the cast explicit. This is backwards-compatible with old Qt versions.
+
\sa toEncoded(), setUrl()
*/
-QUrl QUrl::fromEncoded(const QByteArray &input, ParsingMode mode)
+QUrl QUrl::fromEncoded(QByteArrayView input, ParsingMode mode)
{
- return QUrl(QString::fromUtf8(input.constData(), input.size()), mode);
+ return QUrl(QString::fromUtf8(input), mode);
}
/*!
@@ -3060,17 +3043,6 @@ QString QUrl::fromAce(const QByteArray &domain, QUrl::AceProcessingOptions optio
ForbidLeadingDot /*FIXME: make configurable*/, options);
}
-#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
-/*!
- \since 4.2
- \overload
-*/
-QString QUrl::fromAce(const QByteArray &domain)
-{
- return fromAce(domain, {});
-}
-#endif
-
/*!
\since 6.3
@@ -3094,102 +3066,104 @@ QByteArray QUrl::toAce(const QString &domain, AceProcessingOptions options)
.toLatin1();
}
-#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
-/*!
- \since 4.2
- \overload
-*/
-QByteArray QUrl::toAce(const QString &domain)
-{
- return toAce(domain, {});
-}
-#endif
-
/*!
\internal
- Returns \c true if this URL is "less than" the given \a url. This
+ \fn bool QUrl::operator<(const QUrl &lhs, const QUrl &rhs)
+
+ Returns \c true if URL \a lhs is "less than" URL \a rhs. This
provides a means of ordering URLs.
*/
-bool QUrl::operator <(const QUrl &url) const
+
+Qt::weak_ordering compareThreeWay(const QUrl &lhs, const QUrl &rhs)
{
- if (!d || !url.d) {
- bool thisIsEmpty = !d || d->isEmpty();
- bool thatIsEmpty = !url.d || url.d->isEmpty();
+ if (!lhs.d || !rhs.d) {
+ bool thisIsEmpty = !lhs.d || lhs.d->isEmpty();
+ bool thatIsEmpty = !rhs.d || rhs.d->isEmpty();
// sort an empty URL first
- return thisIsEmpty && !thatIsEmpty;
+ if (thisIsEmpty) {
+ if (!thatIsEmpty)
+ return Qt::weak_ordering::less;
+ else
+ return Qt::weak_ordering::equivalent;
+ } else {
+ return Qt::weak_ordering::greater;
+ }
}
int cmp;
- cmp = d->scheme.compare(url.d->scheme);
+ cmp = lhs.d->scheme.compare(rhs.d->scheme);
if (cmp != 0)
- return cmp < 0;
+ return Qt::compareThreeWay(cmp, 0);
- cmp = d->userName.compare(url.d->userName);
+ cmp = lhs.d->userName.compare(rhs.d->userName);
if (cmp != 0)
- return cmp < 0;
+ return Qt::compareThreeWay(cmp, 0);
- cmp = d->password.compare(url.d->password);
+ cmp = lhs.d->password.compare(rhs.d->password);
if (cmp != 0)
- return cmp < 0;
+ return Qt::compareThreeWay(cmp, 0);
- cmp = d->host.compare(url.d->host);
+ cmp = lhs.d->host.compare(rhs.d->host);
if (cmp != 0)
- return cmp < 0;
+ return Qt::compareThreeWay(cmp, 0);
- if (d->port != url.d->port)
- return d->port < url.d->port;
+ if (lhs.d->port != rhs.d->port)
+ return Qt::compareThreeWay(lhs.d->port, rhs.d->port);
- cmp = d->path.compare(url.d->path);
+ cmp = lhs.d->path.compare(rhs.d->path);
if (cmp != 0)
- return cmp < 0;
+ return Qt::compareThreeWay(cmp, 0);
- if (d->hasQuery() != url.d->hasQuery())
- return url.d->hasQuery();
+ if (lhs.d->hasQuery() != rhs.d->hasQuery())
+ return rhs.d->hasQuery() ? Qt::weak_ordering::less : Qt::weak_ordering::greater;
- cmp = d->query.compare(url.d->query);
+ cmp = lhs.d->query.compare(rhs.d->query);
if (cmp != 0)
- return cmp < 0;
+ return Qt::compareThreeWay(cmp, 0);
- if (d->hasFragment() != url.d->hasFragment())
- return url.d->hasFragment();
+ if (lhs.d->hasFragment() != rhs.d->hasFragment())
+ return rhs.d->hasFragment() ? Qt::weak_ordering::less : Qt::weak_ordering::greater;
- cmp = d->fragment.compare(url.d->fragment);
- return cmp < 0;
+ cmp = lhs.d->fragment.compare(rhs.d->fragment);
+ return Qt::compareThreeWay(cmp, 0);
}
/*!
- Returns \c true if this URL and the given \a url are equal;
+ \fn bool QUrl::operator==(const QUrl &lhs, const QUrl &rhs)
+
+ Returns \c true if \a lhs and \a rhs URLs are equivalent;
otherwise returns \c false.
\sa matches()
*/
-bool QUrl::operator ==(const QUrl &url) const
+
+bool comparesEqual(const QUrl &lhs, const QUrl &rhs)
{
- if (!d && !url.d)
+ if (!lhs.d && !rhs.d)
return true;
- if (!d)
- return url.d->isEmpty();
- if (!url.d)
- return d->isEmpty();
+ if (!lhs.d)
+ return rhs.d->isEmpty();
+ if (!rhs.d)
+ return lhs.d->isEmpty();
// First, compare which sections are present, since it speeds up the
// processing considerably. We just have to ignore the host-is-present flag
// for local files (the "file" protocol), due to the requirements of the
// XDG file URI specification.
int mask = QUrlPrivate::FullUrl;
- if (isLocalFile())
+ if (lhs.isLocalFile())
mask &= ~QUrlPrivate::Host;
- return (d->sectionIsPresent & mask) == (url.d->sectionIsPresent & mask) &&
- d->scheme == url.d->scheme &&
- d->userName == url.d->userName &&
- d->password == url.d->password &&
- d->host == url.d->host &&
- d->port == url.d->port &&
- d->path == url.d->path &&
- d->query == url.d->query &&
- d->fragment == url.d->fragment;
+ return (lhs.d->sectionIsPresent & mask) == (rhs.d->sectionIsPresent & mask) &&
+ lhs.d->scheme == rhs.d->scheme &&
+ lhs.d->userName == rhs.d->userName &&
+ lhs.d->password == rhs.d->password &&
+ lhs.d->host == rhs.d->host &&
+ lhs.d->port == rhs.d->port &&
+ lhs.d->path == rhs.d->path &&
+ lhs.d->query == rhs.d->query &&
+ lhs.d->fragment == rhs.d->fragment;
}
/*!
@@ -3269,20 +3243,18 @@ bool QUrl::matches(const QUrl &url, FormattingOptions options) const
}
/*!
- Returns \c true if this URL and the given \a url are not equal;
+ \fn bool QUrl::operator !=(const QUrl &lhs, const QUrl &rhs)
+
+ Returns \c true if \a lhs and \a rhs URLs are not equal;
otherwise returns \c false.
\sa matches()
*/
-bool QUrl::operator !=(const QUrl &url) const
-{
- return !(*this == url);
-}
/*!
Assigns the specified \a url to this object.
*/
-QUrl &QUrl::operator =(const QUrl &url)
+QUrl &QUrl::operator =(const QUrl &url) noexcept
{
if (!d) {
if (url.d) {
@@ -3401,11 +3373,11 @@ QUrl QUrl::fromLocalFile(const QString &localFile)
QString deslashified = fromNativeSeparators(localFile);
// magic for drives on windows
- if (deslashified.length() > 1 && deslashified.at(1) == QLatin1Char(':') && deslashified.at(0) != QLatin1Char('/')) {
- deslashified.prepend(QLatin1Char('/'));
- } else if (deslashified.startsWith(QLatin1String("//"))) {
+ if (deslashified.size() > 1 && deslashified.at(1) == u':' && deslashified.at(0) != u'/') {
+ deslashified.prepend(u'/');
+ } else if (deslashified.startsWith("//"_L1)) {
// magic for shared drive on windows
- int indexOfPath = deslashified.indexOf(QLatin1Char('/'), 2);
+ qsizetype indexOfPath = deslashified.indexOf(u'/', 2);
QStringView hostSpec = QStringView{deslashified}.mid(2, indexOfPath - 2);
// Check for Windows-specific WebDAV specification: "//host@SSL/path".
if (hostSpec.endsWith(webDavSslTag(), Qt::CaseInsensitive)) {
@@ -3422,7 +3394,7 @@ QUrl QUrl::fromLocalFile(const QString &localFile)
// Path hostname is not a valid URL host, so set it entirely in the path
// (by leaving deslashified unchanged)
} else if (indexOfPath > 2) {
- deslashified = deslashified.right(deslashified.length() - indexOfPath);
+ deslashified = deslashified.right(deslashified.size() - indexOfPath);
} else {
deslashified.clear();
}
@@ -3486,16 +3458,16 @@ bool QUrl::isParentOf(const QUrl &childUrl) const
if (!d)
return ((childUrl.scheme().isEmpty())
&& (childUrl.authority().isEmpty())
- && childPath.length() > 0 && childPath.at(0) == QLatin1Char('/'));
+ && childPath.size() > 0 && childPath.at(0) == u'/');
QString ourPath = path();
return ((childUrl.scheme().isEmpty() || d->scheme == childUrl.scheme())
&& (childUrl.authority().isEmpty() || authority() == childUrl.authority())
&& childPath.startsWith(ourPath)
- && ((ourPath.endsWith(QLatin1Char('/')) && childPath.length() > ourPath.length())
- || (!ourPath.endsWith(QLatin1Char('/'))
- && childPath.length() > ourPath.length() && childPath.at(ourPath.length()) == QLatin1Char('/'))));
+ && ((ourPath.endsWith(u'/') && childPath.size() > ourPath.size())
+ || (!ourPath.endsWith(u'/') && childPath.size() > ourPath.size()
+ && childPath.at(ourPath.size()) == u'/')));
}
@@ -3541,34 +3513,31 @@ QDebug operator<<(QDebug d, const QUrl &url)
}
#endif
-static QString errorMessage(QUrlPrivate::ErrorCode errorCode, const QString &errorSource, int errorPosition)
+static QString errorMessage(QUrlPrivate::ErrorCode errorCode, const QString &errorSource, qsizetype errorPosition)
{
- QChar c = uint(errorPosition) < uint(errorSource.length()) ?
+ QChar c = size_t(errorPosition) < size_t(errorSource.size()) ?
errorSource.at(errorPosition) : QChar(QChar::Null);
switch (errorCode) {
case QUrlPrivate::NoError:
- Q_ASSERT_X(false, "QUrl::errorString",
- "Impossible: QUrl::errorString should have treated this condition");
- Q_UNREACHABLE();
- return QString();
+ Q_UNREACHABLE_RETURN(QString()); // QUrl::errorString should have treated this condition
case QUrlPrivate::InvalidSchemeError: {
- auto msg = QLatin1String("Invalid scheme (character '%1' not permitted)");
+ auto msg = "Invalid scheme (character '%1' not permitted)"_L1;
return msg.arg(c);
}
case QUrlPrivate::InvalidUserNameError:
- return QLatin1String("Invalid user name (character '%1' not permitted)")
+ return "Invalid user name (character '%1' not permitted)"_L1
.arg(c);
case QUrlPrivate::InvalidPasswordError:
- return QLatin1String("Invalid password (character '%1' not permitted)")
+ return "Invalid password (character '%1' not permitted)"_L1
.arg(c);
case QUrlPrivate::InvalidRegNameError:
- if (errorPosition != -1)
- return QLatin1String("Invalid hostname (character '%1' not permitted)")
+ if (errorPosition >= 0)
+ return "Invalid hostname (character '%1' not permitted)"_L1
.arg(c);
else
return QStringLiteral("Invalid hostname (contains invalid characters)");
@@ -3577,9 +3546,9 @@ static QString errorMessage(QUrlPrivate::ErrorCode errorCode, const QString &err
case QUrlPrivate::InvalidIPv6AddressError:
return QStringLiteral("Invalid IPv6 address");
case QUrlPrivate::InvalidCharacterInIPv6Error:
- return QLatin1String("Invalid IPv6 address (character '%1' not permitted)").arg(c);
+ return "Invalid IPv6 address (character '%1' not permitted)"_L1.arg(c);
case QUrlPrivate::InvalidIPvFutureError:
- return QLatin1String("Invalid IPvFuture address (character '%1' not permitted)").arg(c);
+ return "Invalid IPvFuture address (character '%1' not permitted)"_L1.arg(c);
case QUrlPrivate::HostMissingEndBracket:
return QStringLiteral("Expected ']' to match '[' in hostname");
@@ -3589,15 +3558,15 @@ static QString errorMessage(QUrlPrivate::ErrorCode errorCode, const QString &err
return QStringLiteral("Port field was empty");
case QUrlPrivate::InvalidPathError:
- return QLatin1String("Invalid path (character '%1' not permitted)")
+ return "Invalid path (character '%1' not permitted)"_L1
.arg(c);
case QUrlPrivate::InvalidQueryError:
- return QLatin1String("Invalid query (character '%1' not permitted)")
+ return "Invalid query (character '%1' not permitted)"_L1
.arg(c);
case QUrlPrivate::InvalidFragmentError:
- return QLatin1String("Invalid fragment (character '%1' not permitted)")
+ return "Invalid fragment (character '%1' not permitted)"_L1
.arg(c);
case QUrlPrivate::AuthorityPresentAndPathIsRelative:
@@ -3608,20 +3577,14 @@ static QString errorMessage(QUrlPrivate::ErrorCode errorCode, const QString &err
return QStringLiteral("Relative URL's path component contains ':' before any '/'");
}
- Q_ASSERT_X(false, "QUrl::errorString", "Cannot happen, unknown error");
- Q_UNREACHABLE();
- return QString();
+ Q_UNREACHABLE_RETURN(QString());
}
static inline void appendComponentIfPresent(QString &msg, bool present, const char *componentName,
const QString &component)
{
- if (present) {
- msg += QLatin1String(componentName);
- msg += QLatin1Char('"');
- msg += component;
- msg += QLatin1String("\",");
- }
+ if (present)
+ msg += QLatin1StringView(componentName) % u'"' % component % "\","_L1;
}
/*!
@@ -3644,15 +3607,15 @@ QString QUrl::errorString() const
return msg;
QString errorSource;
- int errorPosition = 0;
+ qsizetype errorPosition = 0;
QUrlPrivate::ErrorCode errorCode = d->validityError(&errorSource, &errorPosition);
if (errorCode == QUrlPrivate::NoError)
return msg;
msg += errorMessage(errorCode, errorSource, errorPosition);
- msg += QLatin1String("; source was \"");
+ msg += "; source was \""_L1;
msg += errorSource;
- msg += QLatin1String("\";");
+ msg += "\";"_L1;
appendComponentIfPresent(msg, d->sectionIsPresent & QUrlPrivate::Scheme,
" scheme = ", d->scheme);
appendComponentIfPresent(msg, d->sectionIsPresent & QUrlPrivate::UserInfo,
@@ -3667,7 +3630,7 @@ QString QUrl::errorString() const
" query = ", d->query);
appendComponentIfPresent(msg, d->sectionIsPresent & QUrlPrivate::Fragment,
" fragment = ", d->fragment);
- if (msg.endsWith(QLatin1Char(',')))
+ if (msg.endsWith(u','))
msg.chop(1);
return msg;
}
@@ -3738,8 +3701,8 @@ static QUrl adjustFtpPath(QUrl url)
{
if (url.scheme() == ftpScheme()) {
QString path = url.path(QUrl::PrettyDecoded);
- if (path.startsWith(QLatin1String("//")))
- url.setPath(QLatin1String("/%2F") + QStringView{path}.mid(2), QUrl::TolerantMode);
+ if (path.startsWith("//"_L1))
+ url.setPath("/%2F"_L1 + QStringView{path}.mid(2), QUrl::TolerantMode);
}
return url;
}
@@ -3824,7 +3787,7 @@ QUrl QUrl::fromUserInput(const QString &userInput, const QString &workingDirecto
if (QDir::isAbsolutePath(trimmedString))
return QUrl::fromLocalFile(trimmedString);
- QUrl urlPrepended = QUrl(QLatin1String("http://") + trimmedString, QUrl::TolerantMode);
+ QUrl urlPrepended = QUrl("http://"_L1 + trimmedString, QUrl::TolerantMode);
// Check the most common case of a valid url with a scheme
// We check if the port would be valid by adding the scheme to handle the case host:port
@@ -3836,7 +3799,7 @@ QUrl QUrl::fromUserInput(const QString &userInput, const QString &workingDirecto
// Else, try the prepended one and adjust the scheme from the host name
if (urlPrepended.isValid() && (!urlPrepended.host().isEmpty() || !urlPrepended.path().isEmpty())) {
- int dotIndex = trimmedString.indexOf(QLatin1Char('.'));
+ qsizetype dotIndex = trimmedString.indexOf(u'.');
const QStringView hostscheme = QStringView{trimmedString}.left(dotIndex);
if (hostscheme.compare(ftpScheme(), Qt::CaseInsensitive) == 0)
urlPrepended.setScheme(ftpScheme());