From 0b956cf9682da48174c0fa1dc415a48bdc0d8160 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Sat, 7 Sep 2019 23:59:59 +0200 Subject: [PATCH] util/StringAPI: add memrchr() wrapper --- src/util/StringAPI.hxx | 21 +++++++++++++++++++++ src/util/StringView.hxx | 5 +++++ src/util/WStringAPI.hxx | 15 +++++++++++++++ 3 files changed, 41 insertions(+) diff --git a/src/util/StringAPI.hxx b/src/util/StringAPI.hxx index 0d8878442..fdb918389 100644 --- a/src/util/StringAPI.hxx +++ b/src/util/StringAPI.hxx @@ -94,6 +94,27 @@ StringFindLast(char *haystack, char needle) noexcept return strrchr(haystack, needle); } +gcc_pure gcc_nonnull_all +static inline const char * +StringFindLast(const char *haystack, char needle, size_t size) noexcept +{ +#if defined(__GLIBC__) || defined(__BIONIC__) + /* memrchr() is a GNU extension (and also available on + Android) */ + return (const char *)memrchr(haystack, needle, size); +#else + /* emulate for everybody else */ + const auto *p = haystack + size; + while (p > haystack) { + --p; + if (*p == needle) + return p; + } + + return nullptr; +#endif +} + gcc_pure gcc_nonnull_all static inline const char * StringFindAny(const char *haystack, const char *accept) noexcept diff --git a/src/util/StringView.hxx b/src/util/StringView.hxx index 72d561c9e..2e107dcbe 100644 --- a/src/util/StringView.hxx +++ b/src/util/StringView.hxx @@ -94,6 +94,11 @@ struct BasicStringView : ConstBuffer { return StringFind(data, ch, this->size); } + gcc_pure + pointer_type FindLast(value_type ch) const noexcept { + return StringFindLast(data, ch, size); + } + /** * Split the string at the first occurrence of the given * character. If the character is not found, then the first diff --git a/src/util/WStringAPI.hxx b/src/util/WStringAPI.hxx index 58bc24c87..82864a9a5 100644 --- a/src/util/WStringAPI.hxx +++ b/src/util/WStringAPI.hxx @@ -90,6 +90,21 @@ StringFindLast(wchar_t *haystack, wchar_t needle) noexcept return wcsrchr(haystack, needle); } +gcc_pure gcc_nonnull_all +static inline const wchar_t * +StringFindLast(const wchar_t *haystack, wchar_t needle, size_t size) noexcept +{ + /* there's no wmemrchr() unfortunately */ + const auto *p = haystack + size; + while (p > haystack) { + --p; + if (*p == needle) + return p; + } + + return nullptr; +} + gcc_pure gcc_nonnull_all static inline const wchar_t * StringFindAny(const wchar_t *haystack, const wchar_t *accept) noexcept