From 412262d9447cb16e0bea486f622e126ea57c0429 Mon Sep 17 00:00:00 2001 From: Danil Ovchinnikov Date: Sun, 13 Feb 2022 00:01:06 +0700 Subject: [PATCH 1/5] Add str_contains() function --- builtin-functions/_functions.txt | 1 + runtime/string.inl | 12 ++++++++++++ runtime/string_decl.inl | 1 + runtime/string_functions.cpp | 4 ++++ runtime/string_functions.h | 2 ++ tests/cpp/runtime/string-test.cpp | 24 ++++++++++++++++++++---- 6 files changed, 40 insertions(+), 4 deletions(-) diff --git a/builtin-functions/_functions.txt b/builtin-functions/_functions.txt index af35a1d43f..2c71ffee3e 100644 --- a/builtin-functions/_functions.txt +++ b/builtin-functions/_functions.txt @@ -663,6 +663,7 @@ function substr_compare ($main_str ::: string, $str ::: string, $offset ::: int, function str_starts_with ($haystack ::: string, $needle ::: string) ::: bool; function str_ends_with ($haystack ::: string, $needle ::: string) ::: bool; +function str_contains ($haystack ::: string, $needle ::: string) ::: bool; function trim ($s ::: string, $what ::: string = " \n\r\t\v\0") ::: string; function ltrim ($s ::: string, $what ::: string = " \n\r\t\v\0") ::: string; diff --git a/runtime/string.inl b/runtime/string.inl index 03ac0cf420..29096401a8 100644 --- a/runtime/string.inl +++ b/runtime/string.inl @@ -344,6 +344,18 @@ bool string::ends_with(const string &other) const noexcept { return other.size() > size() ? false : !memcmp(c_str() + (size() - other.size()), other.c_str(), other.size()); } +bool string::contains(const string &other) const noexcept { + if (other.size() > size() ) + return false; + + for (size_type i = 0; i < (size() - other.size() + 1); i++) { + if (memcmp(c_str() + i, other.c_str(), other.size()) == 0) + return true; + } + + return false; +} + const char &string::operator[](size_type pos) const { return p[pos]; } diff --git a/runtime/string_decl.inl b/runtime/string_decl.inl index 6a51c582be..334b88069c 100644 --- a/runtime/string_decl.inl +++ b/runtime/string_decl.inl @@ -96,6 +96,7 @@ public: inline bool empty() const; inline bool starts_with(const string &other) const noexcept; inline bool ends_with(const string &other) const noexcept; + inline bool contains(const string &other) const noexcept; inline const char &operator[](size_type pos) const; inline char &operator[](size_type pos); diff --git a/runtime/string_functions.cpp b/runtime/string_functions.cpp index 7c483b077d..7ed984dcad 100644 --- a/runtime/string_functions.cpp +++ b/runtime/string_functions.cpp @@ -2327,6 +2327,10 @@ bool f$str_ends_with(const string &haystack, const string &needle) { return haystack.ends_with(needle); } +bool f$str_contains(const string &haystack, const string &needle) { + return haystack.contains(needle); +} + string f$trim(const string &s, const string &what) { const char *mask = get_mask(what); diff --git a/runtime/string_functions.h b/runtime/string_functions.h index 28f339c4d1..4f1e3b9f2f 100644 --- a/runtime/string_functions.h +++ b/runtime/string_functions.h @@ -236,6 +236,8 @@ bool f$str_starts_with(const string &haystack, const string &needle); bool f$str_ends_with(const string &haystack, const string &needle); +bool f$str_contains(const string &haystack, const string &needle); + string f$trim(const string &s, const string &what = WHAT); string f$ucfirst(const string &str); diff --git a/tests/cpp/runtime/string-test.cpp b/tests/cpp/runtime/string-test.cpp index 7423fc95ab..0092731866 100644 --- a/tests/cpp/runtime/string-test.cpp +++ b/tests/cpp/runtime/string-test.cpp @@ -56,6 +56,25 @@ TEST(string_test, test_ends_with) { ASSERT_FALSE(str.starts_with(string{"hello world!"})); } +TEST(string_test, test_contains) { + string empty_str{""}; + ASSERT_TRUE(empty_str.contains(string{""})); + ASSERT_FALSE(empty_str.contains(string{"a"})); + + string str{"hello world"}; + ASSERT_TRUE(str.contains(string{"hello"})); + ASSERT_TRUE(str.contains(string{"world"})); + ASSERT_TRUE(str.contains(string{"orld"})); + ASSERT_TRUE(str.contains(string{"o w"})); + ASSERT_TRUE(str.contains(string{"d"})); + ASSERT_TRUE(str.contains(string{""})); + + ASSERT_FALSE(str.contains(string{"hEllo"})); + ASSERT_FALSE(str.contains(string{"o W"})); + + ASSERT_FALSE(str.contains(string{"hello world!"})); +} + TEST(string_test, test_make_const_string_on_memory) { char mem[1024]; @@ -84,10 +103,7 @@ TEST(string_test, test_copy_and_make_not_shared) { TEST(string_test, test_hex_to_int) { for (size_t c = 0; c != 256; ++c) { - if (vk::none_of_equal(c, - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - 'a', 'b', 'c', 'd', 'e', 'f', - 'A', 'B', 'C', 'D', 'E', 'F')) { + if (vk::none_of_equal(c, '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F')) { ASSERT_EQ(hex_to_int(static_cast(c)), 16); } } From fd5a36c7d6412853cff15ce6c9fce3d2efd1a2bf Mon Sep 17 00:00:00 2001 From: Danil Ovchinnikov Date: Sun, 13 Feb 2022 00:08:46 +0700 Subject: [PATCH 2/5] Fix code style --- runtime/string.inl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/string.inl b/runtime/string.inl index 29096401a8..9f20f54624 100644 --- a/runtime/string.inl +++ b/runtime/string.inl @@ -345,7 +345,7 @@ bool string::ends_with(const string &other) const noexcept { } bool string::contains(const string &other) const noexcept { - if (other.size() > size() ) + if (other.size() > size()) return false; for (size_type i = 0; i < (size() - other.size() + 1); i++) { From 791d3505ba2ec9293816e01896bbe543a6751792 Mon Sep 17 00:00:00 2001 From: Danil Ovchinnikov Date: Sun, 13 Feb 2022 12:15:02 +0700 Subject: [PATCH 3/5] Fix code style --- tests/cpp/runtime/string-test.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/cpp/runtime/string-test.cpp b/tests/cpp/runtime/string-test.cpp index 0092731866..53faec110c 100644 --- a/tests/cpp/runtime/string-test.cpp +++ b/tests/cpp/runtime/string-test.cpp @@ -103,7 +103,10 @@ TEST(string_test, test_copy_and_make_not_shared) { TEST(string_test, test_hex_to_int) { for (size_t c = 0; c != 256; ++c) { - if (vk::none_of_equal(c, '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F')) { + if (vk::none_of_equal(c, + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'a', 'b', 'c', 'd', 'e', 'f', + 'A', 'B', 'C', 'D', 'E', 'F')) { ASSERT_EQ(hex_to_int(static_cast(c)), 16); } } From a4a12a26e82c20493531b5d7267c6e32a6fa14f6 Mon Sep 17 00:00:00 2001 From: Danil Ovchinnikov Date: Tue, 15 Feb 2022 09:51:08 +0700 Subject: [PATCH 4/5] Fix test for KPHP --- .../composer/php/test_autoload_files/lib/polyfills/file2.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/python/tests/composer/php/test_autoload_files/lib/polyfills/file2.php b/tests/python/tests/composer/php/test_autoload_files/lib/polyfills/file2.php index 2c8d5e2cb8..c82eed9ac7 100644 --- a/tests/python/tests/composer/php/test_autoload_files/lib/polyfills/file2.php +++ b/tests/python/tests/composer/php/test_autoload_files/lib/polyfills/file2.php @@ -3,8 +3,10 @@ global $global_map; $global_map[__FILE__] = true; +#ifndef KPHP if (!function_exists('str_contains')) { function str_contains(string $haystack, string $needle): bool { return '' === $needle || false !== strpos($haystack, $needle); } } +#endif From fe2baa424155e8781b1e4d0ab88e4310bea0d136 Mon Sep 17 00:00:00 2001 From: Danil Ovchinnikov Date: Wed, 30 Mar 2022 23:41:38 +0700 Subject: [PATCH 5/5] Review fixes --- runtime/string.inl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/runtime/string.inl b/runtime/string.inl index 9f20f54624..f3812a20e8 100644 --- a/runtime/string.inl +++ b/runtime/string.inl @@ -345,12 +345,14 @@ bool string::ends_with(const string &other) const noexcept { } bool string::contains(const string &other) const noexcept { - if (other.size() > size()) + if (other.size() > size()) { return false; + } for (size_type i = 0; i < (size() - other.size() + 1); i++) { - if (memcmp(c_str() + i, other.c_str(), other.size()) == 0) + if (memcmp(c_str() + i, other.c_str(), other.size()) == 0) { return true; + } } return false;