Standardize iFindFirst

iFindFirst was added in the previous commit.  Move it to using
std::ranges::subrange, withi is a direct replacement for boost, rather
than inventing a new type.

Tested: Unit tests pass.
Change-Id: I6d88fc90f34ee0748b52e9fb6438635f9cdbd0a9
Signed-off-by: Ed Tanous <etanous@nvidia.com>
diff --git a/src/utils.hpp b/src/utils.hpp
index e51ed1e..4565db0 100644
--- a/src/utils.hpp
+++ b/src/utils.hpp
@@ -77,8 +77,23 @@
 /// \return true if the dbusValue matched the probe otherwise false.
 bool matchProbe(const nlohmann::json& probe, const DBusValueVariant& dbusValue);
 
-std::pair<FirstIndex, LastIndex> iFindFirst(std::string_view str,
-                                            std::string_view sub);
+inline char asciiToLower(char c)
+{
+    // Converts a character to lower case without relying on std::locale
+    if ('A' <= c && c <= 'Z')
+    {
+        c -= static_cast<char>('A' - 'a');
+    }
+    return c;
+}
+
+template <typename T>
+auto iFindFirst(T&& str, std::string_view sub)
+{
+    return std::ranges::search(str, sub, [](char a, char b) {
+        return asciiToLower(a) == asciiToLower(b);
+    });
+}
 
 template <typename T>
 std::from_chars_result fromCharsWrapper(const std::string_view& str, T& out,