replace boost::ifind_first with std::ranges::search

Use a custom case-insensitive search to remove Boost dependency and
reduce compilation memory usage, keeping original string replacement
behavior.

Change-Id: I5778b208dfdb0082515e92f7bda335beb94c21cb
Signed-off-by: George Liu <liuxiwei@ieisystem.com>
diff --git a/test/test_utils.cpp b/test/test_utils.cpp
new file mode 100644
index 0000000..76570df
--- /dev/null
+++ b/test/test_utils.cpp
@@ -0,0 +1,52 @@
+#include "utils.hpp"
+
+#include <gtest/gtest.h>
+
+TEST(IfindFirstTest, BasicMatch)
+{
+    auto [firstIndex, lastIndex] = iFindFirst("Hello World", "World");
+    EXPECT_EQ(firstIndex, 6);
+    EXPECT_EQ(lastIndex, 11);
+}
+
+TEST(IfindFirstTest, CaseInsensitiveMatch)
+{
+    auto [firstIndex, lastIndex] = iFindFirst("Hello World", "world");
+    EXPECT_EQ(firstIndex, 6);
+    EXPECT_EQ(lastIndex, 11);
+}
+
+TEST(IfindFirstTest, NoMatch)
+{
+    auto [firstIndex, lastIndex] = iFindFirst("Hello World", "Planet");
+    EXPECT_EQ(firstIndex, std::string_view::npos);
+    EXPECT_EQ(lastIndex, std::string_view::npos);
+}
+
+TEST(IfindFirstTest, MatchAtStart)
+{
+    auto [firstIndex, lastIndex] = iFindFirst("Hello World", "HeLLo");
+    EXPECT_EQ(firstIndex, 0);
+    EXPECT_EQ(lastIndex, 5);
+}
+
+TEST(IfindFirstTest, MatchAtEnd)
+{
+    auto [firstIndex, lastIndex] = iFindFirst("Hello World", "LD");
+    EXPECT_EQ(firstIndex, 9);
+    EXPECT_EQ(lastIndex, 11);
+}
+
+TEST(IfindFirstTest, EmptySubstring)
+{
+    auto [firstIndex, lastIndex] = iFindFirst("Hello", "");
+    EXPECT_EQ(firstIndex, std::string_view::npos);
+    EXPECT_EQ(lastIndex, std::string_view::npos);
+}
+
+TEST(IfindFirstTest, EmptyString)
+{
+    auto [firstIndex, lastIndex] = iFindFirst("", "Hello");
+    EXPECT_EQ(firstIndex, std::string_view::npos);
+    EXPECT_EQ(lastIndex, std::string_view::npos);
+}