This is an automated email from the ASF dual-hosted git repository.

junrushao pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tvm-ffi.git


The following commit(s) were added to refs/heads/main by this push:
     new 02d1a96  feat: add starts_with and ends_with to String (#388)
02d1a96 is described below

commit 02d1a9600ac195fc320fe10fe42c978bcdb5e727
Author: Guan-Ming (Wesley) Chiu <[email protected]>
AuthorDate: Fri Jan 9 15:36:26 2026 +0800

    feat: add starts_with and ends_with to String (#388)
    
    ## Why
    
    String pattern matching is essential for validation and parsing in
    compiler infrastructure. Users currently lack efficient prefix/suffix
    checking methods.
    
    ## How
    
    - Add `starts_with(prefix)` method supporting String, const char*, and
    raw pointer with length
    - Add `ends_with(suffix)` method with same overload variants
    - Add tests
---
 include/tvm/ffi/string.h | 70 ++++++++++++++++++++++++++++++++++++++++++++++++
 tests/cpp/test_string.cc | 46 +++++++++++++++++++++++++++++++
 2 files changed, 116 insertions(+)

diff --git a/include/tvm/ffi/string.h b/include/tvm/ffi/string.h
index 59addfa..9c1057a 100644
--- a/include/tvm/ffi/string.h
+++ b/include/tvm/ffi/string.h
@@ -655,6 +655,76 @@ class String {
     return String(data() + pos, rcount);
   }
 
+  /*!
+   * \brief Check if the string starts with a prefix
+   * \param prefix The prefix to check for
+   * \return true if the string starts with prefix, false otherwise
+   */
+  bool starts_with(const String& prefix) const { return 
starts_with(prefix.data(), prefix.size()); }
+
+  /*!
+   * \brief Check if the string starts with a prefix
+   * \param prefix The prefix to check for
+   * \return true if the string starts with prefix, false otherwise
+   */
+  bool starts_with(std::string_view prefix) const {
+    return starts_with(prefix.data(), prefix.size());
+  }
+
+  /*!
+   * \brief Check if the string starts with a prefix
+   * \param prefix The prefix to check for
+   * \return true if the string starts with prefix, false otherwise
+   */
+  bool starts_with(const char* prefix) const { return starts_with(prefix, 
std::strlen(prefix)); }
+
+  /*!
+   * \brief Check if the string starts with a prefix
+   * \param prefix The prefix to check for
+   * \param count The length of the prefix
+   * \return true if the string starts with prefix, false otherwise
+   */
+  bool starts_with(const char* prefix, size_t count) const {
+    if (count > size()) {
+      return false;
+    }
+    return std::memcmp(data(), prefix, count) == 0;
+  }
+
+  /*!
+   * \brief Check if the string ends with a suffix
+   * \param suffix The suffix to check for
+   * \return true if the string ends with suffix, false otherwise
+   */
+  bool ends_with(const String& suffix) const { return ends_with(suffix.data(), 
suffix.size()); }
+
+  /*!
+   * \brief Check if the string ends with a suffix
+   * \param suffix The suffix to check for
+   * \return true if the string ends with suffix, false otherwise
+   */
+  bool ends_with(std::string_view suffix) const { return 
ends_with(suffix.data(), suffix.size()); }
+
+  /*!
+   * \brief Check if the string ends with a suffix
+   * \param suffix The suffix to check for
+   * \return true if the string ends with suffix, false otherwise
+   */
+  bool ends_with(const char* suffix) const { return ends_with(suffix, 
std::strlen(suffix)); }
+
+  /*!
+   * \brief Check if the string ends with a suffix
+   * \param suffix The suffix to check for
+   * \param count The length of the suffix
+   * \return true if the string ends with suffix, false otherwise
+   */
+  bool ends_with(const char* suffix, size_t count) const {
+    if (count > size()) {
+      return false;
+    }
+    return std::memcmp(data() + size() - count, suffix, count) == 0;
+  }
+
   /*!
    * \brief Convert String to an std::string object
    *
diff --git a/tests/cpp/test_string.cc b/tests/cpp/test_string.cc
index afcb651..020cc41 100644
--- a/tests/cpp/test_string.cc
+++ b/tests/cpp/test_string.cc
@@ -482,4 +482,50 @@ TEST(String, Substr) {
   EXPECT_THROW(empty.substr(1), std::out_of_range);
 }
 
+TEST(String, StartsWith) {
+  String s{"hello world"};
+  EXPECT_TRUE(s.starts_with("hello"));
+  EXPECT_TRUE(s.starts_with("h"));
+  EXPECT_TRUE(s.starts_with(""));
+  EXPECT_TRUE(s.starts_with(String{"hello"}));
+  EXPECT_TRUE(s.starts_with(std::string_view{"hello"}));
+  EXPECT_FALSE(s.starts_with("world"));
+  EXPECT_FALSE(s.starts_with("Hello"));
+  EXPECT_FALSE(s.starts_with("hello world extra"));
+  EXPECT_FALSE(s.starts_with(std::string_view{"world"}));
+
+  String empty{""};
+  EXPECT_TRUE(empty.starts_with(""));
+  EXPECT_TRUE(empty.starts_with(std::string_view{""}));
+  EXPECT_FALSE(empty.starts_with("x"));
+
+  String single{"x"};
+  EXPECT_TRUE(single.starts_with("x"));
+  EXPECT_TRUE(single.starts_with(""));
+  EXPECT_FALSE(single.starts_with("xy"));
+}
+
+TEST(String, EndsWith) {
+  String s{"hello world"};
+  EXPECT_TRUE(s.ends_with("world"));
+  EXPECT_TRUE(s.ends_with("d"));
+  EXPECT_TRUE(s.ends_with(""));
+  EXPECT_TRUE(s.ends_with(String{"world"}));
+  EXPECT_TRUE(s.ends_with(std::string_view{"world"}));
+  EXPECT_FALSE(s.ends_with("hello"));
+  EXPECT_FALSE(s.ends_with("World"));
+  EXPECT_FALSE(s.ends_with("extra hello world"));
+  EXPECT_FALSE(s.ends_with(std::string_view{"hello"}));
+
+  String empty{""};
+  EXPECT_TRUE(empty.ends_with(""));
+  EXPECT_TRUE(empty.ends_with(std::string_view{""}));
+  EXPECT_FALSE(empty.ends_with("x"));
+
+  String single{"x"};
+  EXPECT_TRUE(single.ends_with("x"));
+  EXPECT_TRUE(single.ends_with(""));
+  EXPECT_FALSE(single.ends_with("yx"));
+}
+
 }  // namespace

Reply via email to