From 021ae44a34a4b69e56e89ab46575cd03aa139284 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Fri, 26 Jul 2024 11:50:11 -0400 Subject: [PATCH] adding some support for lifetime bounds (#705) * adding some support for lifetime bounds * lint --- include/ada/common_defs.h | 12 ++++++++++++ include/ada/url_aggregator-inl.h | 4 ++-- include/ada/url_aggregator.h | 26 ++++++++++++++++---------- src/url_aggregator.cpp | 27 ++++++++++++++++++--------- 4 files changed, 48 insertions(+), 21 deletions(-) diff --git a/include/ada/common_defs.h b/include/ada/common_defs.h index cefed4edf..e7f4a5e72 100644 --- a/include/ada/common_defs.h +++ b/include/ada/common_defs.h @@ -298,4 +298,16 @@ namespace ada { #define ADA_NEON 1 #endif +#ifndef __has_cpp_attribute +#define ada_lifetime_bound +#elif __has_cpp_attribute(msvc::lifetimebound) +#define ada_lifetime_bound [[msvc::lifetimebound]] +#elif __has_cpp_attribute(clang::lifetimebound) +#define ada_lifetime_bound [[clang::lifetimebound]] +#elif __has_cpp_attribute(lifetimebound) +#define ada_lifetime_bound [[lifetimebound]] +#else +#define ada_lifetime_bound +#endif + #endif // ADA_COMMON_DEFS_H diff --git a/include/ada/url_aggregator-inl.h b/include/ada/url_aggregator-inl.h index af66997dd..6813f0436 100644 --- a/include/ada/url_aggregator-inl.h +++ b/include/ada/url_aggregator-inl.h @@ -844,8 +844,8 @@ inline bool url_aggregator::has_port() const noexcept { buffer[components.host_end + 1] == '.'; } -[[nodiscard]] inline std::string_view url_aggregator::get_href() - const noexcept { +[[nodiscard]] inline std::string_view url_aggregator::get_href() const noexcept + ada_lifetime_bound { ada_log("url_aggregator::get_href"); return buffer; } diff --git a/include/ada/url_aggregator.h b/include/ada/url_aggregator.h index b24c2db75..0a81a1094 100644 --- a/include/ada/url_aggregator.h +++ b/include/ada/url_aggregator.h @@ -57,35 +57,38 @@ struct url_aggregator : url_base { * @see https://url.spec.whatwg.org/#dom-url-href * @see https://url.spec.whatwg.org/#concept-url-serializer */ - [[nodiscard]] inline std::string_view get_href() const noexcept; + [[nodiscard]] inline std::string_view get_href() const noexcept + ada_lifetime_bound; /** * The username getter steps are to return this's URL's username. * This function does not allocate memory. * @return a lightweight std::string_view. * @see https://url.spec.whatwg.org/#dom-url-username */ - [[nodiscard]] std::string_view get_username() const noexcept; + [[nodiscard]] std::string_view get_username() const noexcept + ada_lifetime_bound; /** * The password getter steps are to return this's URL's password. * This function does not allocate memory. * @return a lightweight std::string_view. * @see https://url.spec.whatwg.org/#dom-url-password */ - [[nodiscard]] std::string_view get_password() const noexcept; + [[nodiscard]] std::string_view get_password() const noexcept + ada_lifetime_bound; /** * Return this's URL's port, serialized. * This function does not allocate memory. * @return a lightweight std::string_view. * @see https://url.spec.whatwg.org/#dom-url-port */ - [[nodiscard]] std::string_view get_port() const noexcept; + [[nodiscard]] std::string_view get_port() const noexcept ada_lifetime_bound; /** * Return U+0023 (#), followed by this's URL's fragment. * This function does not allocate memory. * @return a lightweight std::string_view.. * @see https://url.spec.whatwg.org/#dom-url-hash */ - [[nodiscard]] std::string_view get_hash() const noexcept; + [[nodiscard]] std::string_view get_hash() const noexcept ada_lifetime_bound; /** * Return url's host, serialized, followed by U+003A (:) and url's port, * serialized. @@ -94,7 +97,7 @@ struct url_aggregator : url_base { * @return a lightweight std::string_view. * @see https://url.spec.whatwg.org/#dom-url-host */ - [[nodiscard]] std::string_view get_host() const noexcept; + [[nodiscard]] std::string_view get_host() const noexcept ada_lifetime_bound; /** * Return this's URL's host, serialized. * This function does not allocate memory. @@ -102,7 +105,8 @@ struct url_aggregator : url_base { * @return a lightweight std::string_view. * @see https://url.spec.whatwg.org/#dom-url-hostname */ - [[nodiscard]] std::string_view get_hostname() const noexcept; + [[nodiscard]] std::string_view get_hostname() const noexcept + ada_lifetime_bound; /** * The pathname getter steps are to return the result of URL path serializing * this's URL. @@ -110,7 +114,8 @@ struct url_aggregator : url_base { * @return a lightweight std::string_view. * @see https://url.spec.whatwg.org/#dom-url-pathname */ - [[nodiscard]] std::string_view get_pathname() const noexcept; + [[nodiscard]] std::string_view get_pathname() const noexcept + ada_lifetime_bound; /** * Compute the pathname length in bytes without instantiating a view or a * string. @@ -124,7 +129,7 @@ struct url_aggregator : url_base { * @return a lightweight std::string_view. * @see https://url.spec.whatwg.org/#dom-url-search */ - [[nodiscard]] std::string_view get_search() const noexcept; + [[nodiscard]] std::string_view get_search() const noexcept ada_lifetime_bound; /** * The protocol getter steps are to return this's URL's scheme, followed by * U+003A (:). @@ -132,7 +137,8 @@ struct url_aggregator : url_base { * @return a lightweight std::string_view. * @see https://url.spec.whatwg.org/#dom-url-protocol */ - [[nodiscard]] std::string_view get_protocol() const noexcept; + [[nodiscard]] std::string_view get_protocol() const noexcept + ada_lifetime_bound; /** * A URL includes credentials if its username or password is not the empty diff --git a/src/url_aggregator.cpp b/src/url_aggregator.cpp index c6472a2c7..d7c387d6a 100644 --- a/src/url_aggregator.cpp +++ b/src/url_aggregator.cpp @@ -646,7 +646,8 @@ bool url_aggregator::set_hostname(const std::string_view input) { return "null"; } -[[nodiscard]] std::string_view url_aggregator::get_username() const noexcept { +[[nodiscard]] std::string_view url_aggregator::get_username() const noexcept + ada_lifetime_bound { ada_log("url_aggregator::get_username"); if (has_non_empty_username()) { return helpers::substring(buffer, components.protocol_end + 2, @@ -655,7 +656,8 @@ bool url_aggregator::set_hostname(const std::string_view input) { return ""; } -[[nodiscard]] std::string_view url_aggregator::get_password() const noexcept { +[[nodiscard]] std::string_view url_aggregator::get_password() const noexcept + ada_lifetime_bound { ada_log("url_aggregator::get_password"); if (has_non_empty_password()) { return helpers::substring(buffer, components.username_end + 1, @@ -664,7 +666,8 @@ bool url_aggregator::set_hostname(const std::string_view input) { return ""; } -[[nodiscard]] std::string_view url_aggregator::get_port() const noexcept { +[[nodiscard]] std::string_view url_aggregator::get_port() const noexcept + ada_lifetime_bound { ada_log("url_aggregator::get_port"); if (components.port == url_components::omitted) { return ""; @@ -673,7 +676,8 @@ bool url_aggregator::set_hostname(const std::string_view input) { components.pathname_start); } -[[nodiscard]] std::string_view url_aggregator::get_hash() const noexcept { +[[nodiscard]] std::string_view url_aggregator::get_hash() const noexcept + ada_lifetime_bound { ada_log("url_aggregator::get_hash"); // If this's URL's fragment is either null or the empty string, then return // the empty string. Return U+0023 (#), followed by this's URL's fragment. @@ -686,7 +690,8 @@ bool url_aggregator::set_hostname(const std::string_view input) { return helpers::substring(buffer, components.hash_start); } -[[nodiscard]] std::string_view url_aggregator::get_host() const noexcept { +[[nodiscard]] std::string_view url_aggregator::get_host() const noexcept + ada_lifetime_bound { ada_log("url_aggregator::get_host"); // Technically, we should check if there is a hostname, but // the code below works even if there isn't. @@ -704,7 +709,8 @@ bool url_aggregator::set_hostname(const std::string_view input) { return helpers::substring(buffer, start, components.pathname_start); } -[[nodiscard]] std::string_view url_aggregator::get_hostname() const noexcept { +[[nodiscard]] std::string_view url_aggregator::get_hostname() const noexcept + ada_lifetime_bound { ada_log("url_aggregator::get_hostname"); // Technically, we should check if there is a hostname, but // the code below works even if there isn't. @@ -718,7 +724,8 @@ bool url_aggregator::set_hostname(const std::string_view input) { return helpers::substring(buffer, start, components.host_end); } -[[nodiscard]] std::string_view url_aggregator::get_pathname() const noexcept { +[[nodiscard]] std::string_view url_aggregator::get_pathname() const noexcept + ada_lifetime_bound { ada_log("url_aggregator::get_pathname pathname_start = ", components.pathname_start, " buffer.size() = ", buffer.size(), " components.search_start = ", components.search_start, @@ -732,7 +739,8 @@ bool url_aggregator::set_hostname(const std::string_view input) { return helpers::substring(buffer, components.pathname_start, ending_index); } -[[nodiscard]] std::string_view url_aggregator::get_search() const noexcept { +[[nodiscard]] std::string_view url_aggregator::get_search() const noexcept + ada_lifetime_bound { ada_log("url_aggregator::get_search"); // If this's URL's query is either null or the empty string, then return the // empty string. Return U+003F (?), followed by this's URL's query. @@ -749,7 +757,8 @@ bool url_aggregator::set_hostname(const std::string_view input) { return helpers::substring(buffer, components.search_start, ending_index); } -[[nodiscard]] std::string_view url_aggregator::get_protocol() const noexcept { +[[nodiscard]] std::string_view url_aggregator::get_protocol() const noexcept + ada_lifetime_bound { ada_log("url_aggregator::get_protocol"); return helpers::substring(buffer, 0, components.protocol_end); }