From 06581636a17e7481e0e3dfcba01e4a3b3fd9f446 Mon Sep 17 00:00:00 2001 From: Vladimir Golovnev Date: Mon, 7 Aug 2023 11:21:32 +0300 Subject: [PATCH] Utilize QByteArrayView PR #19417. --- src/base/http/requestparser.cpp | 41 +++++++++++++------------ src/base/http/requestparser.h | 6 ++-- src/base/search/searchpluginmanager.cpp | 6 ++-- src/base/utils/bytearray.cpp | 20 +++--------- src/base/utils/bytearray.h | 7 ++--- src/base/utils/foreignapps.cpp | 2 +- src/base/utils/password.cpp | 6 ++-- 7 files changed, 38 insertions(+), 50 deletions(-) diff --git a/src/base/http/requestparser.cpp b/src/base/http/requestparser.cpp index 2568e4a55..497077707 100644 --- a/src/base/http/requestparser.cpp +++ b/src/base/http/requestparser.cpp @@ -32,6 +32,7 @@ #include +#include #include #include #include @@ -50,10 +51,10 @@ namespace { const QByteArray EOH = QByteArray(CRLF).repeated(2); - const QByteArray viewWithoutEndingWith(const QByteArray &in, const QByteArray &str) + const QByteArrayView viewWithoutEndingWith(const QByteArrayView in, const QByteArrayView str) { if (in.endsWith(str)) - return QByteArray::fromRawData(in.constData(), (in.size() - str.size())); + return in.chopped(str.size()); return in; } @@ -81,7 +82,7 @@ RequestParser::ParseResult RequestParser::parse(const QByteArray &data) return RequestParser().doParse(data); } -RequestParser::ParseResult RequestParser::doParse(const QByteArray &data) +RequestParser::ParseResult RequestParser::doParse(const QByteArrayView data) { // we don't handle malformed requests which use double `LF` as delimiter const int headerEnd = data.indexOf(EOH); @@ -130,7 +131,7 @@ RequestParser::ParseResult RequestParser::doParse(const QByteArray &data) if (contentLength > 0) { - const QByteArray httpBodyView = midView(data, headerLength, contentLength); + const QByteArrayView httpBodyView = data.mid(headerLength, contentLength); if (httpBodyView.length() < contentLength) { qDebug() << Q_FUNC_INFO << "incomplete request"; @@ -204,27 +205,27 @@ bool RequestParser::parseRequestLine(const QString &line) // Request Target const QByteArray url {match.captured(2).toLatin1()}; const int sepPos = url.indexOf('?'); - const QByteArray pathComponent = ((sepPos == -1) ? url : midView(url, 0, sepPos)); + const QByteArrayView pathComponent = ((sepPos == -1) ? url : QByteArrayView(url).mid(0, sepPos)); - m_request.path = QString::fromUtf8(QByteArray::fromPercentEncoding(pathComponent)); + m_request.path = QString::fromUtf8(QByteArray::fromPercentEncoding(pathComponent.toByteArray())); if (sepPos >= 0) { - const QByteArray query = midView(url, (sepPos + 1)); + const QByteArrayView query = url.mid(sepPos + 1); // [rfc3986] 2.4 When to Encode or Decode // URL components should be separated before percent-decoding - for (const QByteArray ¶m : asConst(splitToViews(query, "&"))) + for (const QByteArrayView ¶m : asConst(splitToViews(query, "&"))) { const int eqCharPos = param.indexOf('='); if (eqCharPos <= 0) continue; // ignores params without name - const QByteArray nameComponent = midView(param, 0, eqCharPos); - const QByteArray valueComponent = midView(param, (eqCharPos + 1)); - const QString paramName = QString::fromUtf8(QByteArray::fromPercentEncoding(nameComponent).replace('+', ' ')); + const QByteArrayView nameComponent = param.mid(0, eqCharPos); + const QByteArrayView valueComponent = param.mid(eqCharPos + 1); + const QString paramName = QString::fromUtf8(QByteArray::fromPercentEncoding(nameComponent.toByteArray()).replace('+', ' ')); const QByteArray paramValue = valueComponent.isNull() ? QByteArray("") - : QByteArray::fromPercentEncoding(valueComponent).replace('+', ' '); + : QByteArray::fromPercentEncoding(valueComponent.toByteArray()).replace('+', ' '); m_request.query[paramName] = paramValue; } @@ -236,7 +237,7 @@ bool RequestParser::parseRequestLine(const QString &line) return true; } -bool RequestParser::parsePostMessage(const QByteArray &data) +bool RequestParser::parsePostMessage(const QByteArrayView data) { // parse POST message-body const QString contentType = m_request.headers[HEADER_CONTENT_TYPE]; @@ -246,7 +247,7 @@ bool RequestParser::parsePostMessage(const QByteArray &data) if (contentTypeLower.startsWith(CONTENT_TYPE_FORM_ENCODED)) { // [URL Standard] 5.1 application/x-www-form-urlencoded parsing - const QByteArray processedData = QByteArray(data).replace('+', ' '); + const QByteArray processedData = data.toByteArray().replace('+', ' '); QListIterator i(QUrlQuery(QString::fromUtf8(processedData)).queryItems(QUrl::FullyDecoded)); while (i.hasNext()) @@ -281,7 +282,7 @@ bool RequestParser::parsePostMessage(const QByteArray &data) // split data by "dash-boundary" const QByteArray dashDelimiter = QByteArray("--") + delimiter + CRLF; - QVector multipart = splitToViews(data, dashDelimiter, Qt::SkipEmptyParts); + QList multipart = splitToViews(data, dashDelimiter, Qt::SkipEmptyParts); if (multipart.isEmpty()) { qWarning() << Q_FUNC_INFO << "multipart empty"; @@ -292,7 +293,7 @@ bool RequestParser::parsePostMessage(const QByteArray &data) const QByteArray endDelimiter = QByteArray("--") + delimiter + QByteArray("--") + CRLF; multipart.push_back(viewWithoutEndingWith(multipart.takeLast(), endDelimiter)); - return std::all_of(multipart.cbegin(), multipart.cend(), [this](const QByteArray &part) + return std::all_of(multipart.cbegin(), multipart.cend(), [this](const QByteArrayView &part) { return this->parseFormData(part); }); @@ -302,7 +303,7 @@ bool RequestParser::parsePostMessage(const QByteArray &data) return false; } -bool RequestParser::parseFormData(const QByteArray &data) +bool RequestParser::parseFormData(const QByteArrayView data) { const int eohPos = data.indexOf(EOH); @@ -312,8 +313,8 @@ bool RequestParser::parseFormData(const QByteArray &data) return false; } - const QString headers = QString::fromLatin1(Utils::ByteArray::midView(data, 0, eohPos)); - const QByteArray payload = viewWithoutEndingWith(Utils::ByteArray::midView(data, (eohPos + EOH.size()), data.size()), CRLF); + const QString headers = QString::fromLatin1(data.mid(0, eohPos)); + const QByteArrayView payload = viewWithoutEndingWith(data.mid((eohPos + EOH.size()), data.size()), CRLF); HeaderMap headersMap; const QList headerLines = QStringView(headers).split(QString::fromLatin1(CRLF), Qt::SkipEmptyParts); @@ -348,7 +349,7 @@ bool RequestParser::parseFormData(const QByteArray &data) if (headersMap.contains(filename)) { - m_request.files.append({headersMap[filename], headersMap[HEADER_CONTENT_TYPE], payload}); + m_request.files.append({headersMap[filename], headersMap[HEADER_CONTENT_TYPE], payload.toByteArray()}); } else if (headersMap.contains(name)) { diff --git a/src/base/http/requestparser.h b/src/base/http/requestparser.h index b55907ea4..13b19f3ba 100644 --- a/src/base/http/requestparser.h +++ b/src/base/http/requestparser.h @@ -60,12 +60,12 @@ namespace Http private: RequestParser() = default; - ParseResult doParse(const QByteArray &data); + ParseResult doParse(QByteArrayView data); bool parseStartLines(QStringView data); bool parseRequestLine(const QString &line); - bool parsePostMessage(const QByteArray &data); - bool parseFormData(const QByteArray &data); + bool parsePostMessage(QByteArrayView data); + bool parseFormData(QByteArrayView data); Request m_request; }; diff --git a/src/base/search/searchpluginmanager.cpp b/src/base/search/searchpluginmanager.cpp index d927006d2..2127746d3 100644 --- a/src/base/search/searchpluginmanager.cpp +++ b/src/base/search/searchpluginmanager.cpp @@ -580,14 +580,14 @@ void SearchPluginManager::parseVersionInfo(const QByteArray &info) QHash updateInfo; int numCorrectData = 0; - const QVector lines = Utils::ByteArray::splitToViews(info, "\n", Qt::SkipEmptyParts); - for (QByteArray line : lines) + const QList lines = Utils::ByteArray::splitToViews(info, "\n", Qt::SkipEmptyParts); + for (QByteArrayView line : lines) { line = line.trimmed(); if (line.isEmpty()) continue; if (line.startsWith('#')) continue; - const QVector list = Utils::ByteArray::splitToViews(line, ":", Qt::SkipEmptyParts); + const QList list = Utils::ByteArray::splitToViews(line, ":", Qt::SkipEmptyParts); if (list.size() != 2) continue; const auto pluginName = QString::fromUtf8(list.first().trimmed()); diff --git a/src/base/utils/bytearray.cpp b/src/base/utils/bytearray.cpp index d55711742..fce938885 100644 --- a/src/base/utils/bytearray.cpp +++ b/src/base/utils/bytearray.cpp @@ -30,14 +30,15 @@ #include "bytearray.h" #include -#include +#include +#include -QVector Utils::ByteArray::splitToViews(const QByteArray &in, const QByteArray &sep, const Qt::SplitBehavior behavior) +QList Utils::ByteArray::splitToViews(const QByteArrayView in, const QByteArrayView sep, const Qt::SplitBehavior behavior) { if (sep.isEmpty()) return {in}; - QVector ret; + QList ret; ret.reserve((behavior == Qt::KeepEmptyParts) ? (1 + (in.size() / sep.size())) : (1 + (in.size() / (sep.size() + 1)))); @@ -49,7 +50,7 @@ QVector Utils::ByteArray::splitToViews(const QByteArray &in, const Q end = in.size(); // omit empty parts - const QByteArray part = QByteArray::fromRawData((in.constData() + head), (end - head)); + const QByteArrayView part = in.mid(head, (end - head)); if (!part.isEmpty() || (behavior == Qt::KeepEmptyParts)) ret += part; @@ -59,17 +60,6 @@ QVector Utils::ByteArray::splitToViews(const QByteArray &in, const Q return ret; } -const QByteArray Utils::ByteArray::midView(const QByteArray &in, const int pos, const int len) -{ - if ((pos < 0) || (pos >= in.size()) || (len == 0)) - return {}; - - const int validLen = ((len < 0) || (pos + len) >= in.size()) - ? in.size() - pos - : len; - return QByteArray::fromRawData(in.constData() + pos, validLen); -} - QByteArray Utils::ByteArray::toBase32(const QByteArray &in) { const char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; diff --git a/src/base/utils/bytearray.h b/src/base/utils/bytearray.h index 792a4d1e7..c054256de 100644 --- a/src/base/utils/bytearray.h +++ b/src/base/utils/bytearray.h @@ -33,15 +33,12 @@ #include class QByteArray; +class QByteArrayView; namespace Utils::ByteArray { // Mimic QStringView(in).split(sep, behavior) - QVector splitToViews(const QByteArray &in, const QByteArray &sep, Qt::SplitBehavior behavior = Qt::KeepEmptyParts); - - // Mimic QByteArray::mid(pos, len) but instead of returning a full-copy, - // we only return a partial view - const QByteArray midView(const QByteArray &in, int pos, int len = -1); + QList splitToViews(QByteArrayView in, QByteArrayView sep, Qt::SplitBehavior behavior = Qt::KeepEmptyParts); QByteArray toBase32(const QByteArray &in); } diff --git a/src/base/utils/foreignapps.cpp b/src/base/utils/foreignapps.cpp index 683c19ee3..3249b51e6 100644 --- a/src/base/utils/foreignapps.cpp +++ b/src/base/utils/foreignapps.cpp @@ -64,7 +64,7 @@ namespace // Software 'Anaconda' installs its own python interpreter // and `python --version` returns a string like this: // "Python 3.4.3 :: Anaconda 2.3.0 (64-bit)" - const QVector outputSplit = Utils::ByteArray::splitToViews(procOutput, " ", Qt::SkipEmptyParts); + const QList outputSplit = Utils::ByteArray::splitToViews(procOutput, " ", Qt::SkipEmptyParts); if (outputSplit.size() <= 1) return false; diff --git a/src/base/utils/password.cpp b/src/base/utils/password.cpp index 0351aff64..97abdad70 100644 --- a/src/base/utils/password.cpp +++ b/src/base/utils/password.cpp @@ -99,12 +99,12 @@ bool Utils::Password::PBKDF2::verify(const QByteArray &secret, const QString &pa bool Utils::Password::PBKDF2::verify(const QByteArray &secret, const QByteArray &password) { - const QVector list = ByteArray::splitToViews(secret, ":", Qt::SkipEmptyParts); + const QList list = ByteArray::splitToViews(secret, ":", Qt::SkipEmptyParts); if (list.size() != 2) return false; - const QByteArray salt = QByteArray::fromBase64(list[0]); - const QByteArray key = QByteArray::fromBase64(list[1]); + const QByteArray salt = QByteArray::fromBase64(list[0].toByteArray()); + const QByteArray key = QByteArray::fromBase64(list[1].toByteArray()); std::array outBuf {}; const int hmacResult = PKCS5_PBKDF2_HMAC(password.constData(), password.size()