From 7897ec88f426773cea38ce8c21091a05718a09e7 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 14 Dec 2023 15:31:38 +0100 Subject: [PATCH] QHttpHeaders: add value(name, fall-back) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The vast majority of header fields appear only once, but there was no efficient way to get that value: values() returns as a QList (allocating) while combinedValue() returns a QByteArray constructed from values().join() (also allocating). It follows that the QHttpHeaders API is incomplete (lacks an efficient basis of operations in EoP terms). Add a value() function that returns either the value or a user-provided fall-back as a QByteArrayView. Unlike values() and combinedValue(), this function can be noexcept, greatly improving codegen for callers. Found in API review. Pick-to: 6.7 Task-number: QTBUG-107042 Change-Id: I2da20815fd46fdd7f150c224f41eee53abed313e Reviewed-by: Juha Vuolle Reviewed-by: MÃ¥rten Nordheim --- src/network/access/qhttpheaders.cpp | 23 +++++++++++++++++++ src/network/access/qhttpheaders.h | 3 +++ .../access/qhttpheaders/tst_qhttpheaders.cpp | 4 +++- 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/network/access/qhttpheaders.cpp b/src/network/access/qhttpheaders.cpp index de2f7e148a4..683eab21d4d 100644 --- a/src/network/access/qhttpheaders.cpp +++ b/src/network/access/qhttpheaders.cpp @@ -974,6 +974,29 @@ void QHttpHeaders::removeAt(qsizetype i) d->headers.removeAt(i); } +/*! + Returns the value of the (first) header \a name, or \a defaultValue if it + doesn't exist. + + \sa value(QHttpHeaders::WellKnownHeader, QByteArrayView) +*/ +QByteArrayView QHttpHeaders::value(QAnyStringView name, QByteArrayView defaultValue) const noexcept +{ + for (const auto &h : std::as_const(d->headers)) { + if (headerNameIs(h, name)) + return h.value; + } + return defaultValue; +} + +/*! + \overload value(QAnyStringView, QByteArrayView) +*/ +QByteArrayView QHttpHeaders::value(WellKnownHeader name, QByteArrayView defaultValue) const noexcept +{ + return value(headerNames[qToUnderlying(name)], defaultValue); +} + /*! Returns the values of header \a name in a list. Returns an empty list if header with \a name doesn't exist. diff --git a/src/network/access/qhttpheaders.h b/src/network/access/qhttpheaders.h index 636f535c88a..98b4ad62d1a 100644 --- a/src/network/access/qhttpheaders.h +++ b/src/network/access/qhttpheaders.h @@ -237,6 +237,9 @@ public: Q_NETWORK_EXPORT void removeAll(WellKnownHeader name); Q_NETWORK_EXPORT void removeAt(qsizetype i); + Q_NETWORK_EXPORT QByteArrayView value(QAnyStringView name, QByteArrayView defaultValue = {}) const noexcept; + Q_NETWORK_EXPORT QByteArrayView value(WellKnownHeader name, QByteArrayView defaultValue = {}) const noexcept; + Q_NETWORK_EXPORT QList values(QAnyStringView name) const; Q_NETWORK_EXPORT QList values(WellKnownHeader name) const; diff --git a/tests/auto/network/access/qhttpheaders/tst_qhttpheaders.cpp b/tests/auto/network/access/qhttpheaders/tst_qhttpheaders.cpp index 8e6c77e3dd8..a88506fbfed 100644 --- a/tests/auto/network/access/qhttpheaders/tst_qhttpheaders.cpp +++ b/tests/auto/network/access/qhttpheaders/tst_qhttpheaders.cpp @@ -168,9 +168,10 @@ void tst_QHttpHeaders::accessors() QVERIFY(h1.has(QHttpHeaders::WellKnownHeader::Accept)); QVERIFY(h1.has("accept")); - // values() + // values()/value() #define EXISTS_NOT(H, N) do { \ QVERIFY(!H.has(N)); \ + QCOMPARE(H.value(N, "ENOENT"), "ENOENT"); \ const auto values = H.values(N); \ QVERIFY(values.isEmpty()); \ QVERIFY(H.combinedValue(N).isNull()); \ @@ -180,6 +181,7 @@ void tst_QHttpHeaders::accessors() const std::array expected = { __VA_ARGS__ }; \ static_assert(std::tuple_size_v == X); \ QVERIFY(H.has(N)); \ + QCOMPARE(H.value(N, "ENOENT"), expected.front()); \ const auto values = H.values(N); \ QCOMPARE(values.size(), X); \ QCOMPARE(values.front(), expected.front()); \