This is an automated email from the ASF dual-hosted git repository.
hsluoyz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/casbin-cpp.git
The following commit(s) were added to refs/heads/master by this push:
new 8acc470 feat: add keyMatch5 built-in function
8acc470 is described below
commit 8acc4702857dbf28c2a8f54eb3079f859cbad2e5
Author: Yang Luo <[email protected]>
AuthorDate: Sat Oct 31 09:10:03 2026 +0800
feat: add keyMatch5 built-in function
---
casbin/model/evaluator.cpp | 1 +
casbin/util/built_in_functions.cpp | 7 +++++
include/casbin/model/exprtk_config.h | 4 +++
include/casbin/util/built_in_functions.h | 5 ++++
tests/built_in_functions_test.cpp | 47 ++++++++++++++++++++++++++++++++
5 files changed, 64 insertions(+)
diff --git a/casbin/model/evaluator.cpp b/casbin/model/evaluator.cpp
index 2052ecd..69dbe2d 100644
--- a/casbin/model/evaluator.cpp
+++ b/casbin/model/evaluator.cpp
@@ -83,6 +83,7 @@ void ExprtkEvaluator::LoadFunctions() {
AddFunction("keyMatch2",
ExprtkFunctionFactory::GetExprtkFunction(ExprtkFunctionType::KeyMatch2, 2));
AddFunction("keyMatch3",
ExprtkFunctionFactory::GetExprtkFunction(ExprtkFunctionType::KeyMatch3, 2));
AddFunction("keyMatch4",
ExprtkFunctionFactory::GetExprtkFunction(ExprtkFunctionType::KeyMatch4, 2));
+ AddFunction("keyMatch5",
ExprtkFunctionFactory::GetExprtkFunction(ExprtkFunctionType::KeyMatch5, 2));
AddFunction("regexMatch",
ExprtkFunctionFactory::GetExprtkFunction(ExprtkFunctionType::RegexMatch, 2));
AddFunction("ipMatch",
ExprtkFunctionFactory::GetExprtkFunction(ExprtkFunctionType::IpMatch, 2));
AddFunction("keyGet",
ExprtkFunctionFactory::GetExprtkFunction(ExprtkFunctionType::KeyGet, 2));
diff --git a/casbin/util/built_in_functions.cpp
b/casbin/util/built_in_functions.cpp
index 6ca4cb6..c844b5d 100644
--- a/casbin/util/built_in_functions.cpp
+++ b/casbin/util/built_in_functions.cpp
@@ -204,6 +204,13 @@ bool KeyMatch4(const std::string& key1, const std::string&
key2) {
return true;
}
+// KeyMatch5 determines whether key1 matches the pattern of key2 (similar to
RESTful path), key2 can contain a *.
+// The query string in key1 is ignored.
+// For example, "/foo/bar?status=1&type=2" matches "/foo/bar",
"/parent/child1" matches "/parent/*" and "/parent/{id}"
+bool KeyMatch5(const std::string& key1, const std::string& key2) {
+ return KeyMatch3(key1.substr(0, key1.find('?')), key2);
+}
+
// RegexMatch determines whether key1 matches the pattern of key2 in regular
expression.
bool RegexMatch(const std::string& key1, const std::string& key2) {
std::regex regex_s(key2);
diff --git a/include/casbin/model/exprtk_config.h
b/include/casbin/model/exprtk_config.h
index 9ce6a96..e585049 100644
--- a/include/casbin/model/exprtk_config.h
+++ b/include/casbin/model/exprtk_config.h
@@ -234,6 +234,7 @@ enum class ExprtkFunctionType {
KeyMatch2,
KeyMatch3,
KeyMatch4,
+ KeyMatch5,
RegexMatch,
IpMatch,
KeyGet,
@@ -276,6 +277,9 @@ public:
case ExprtkFunctionType::KeyMatch4:
func = std::make_shared<ExprtkMatchFunction>(idenfier,
KeyMatch4);
break;
+ case ExprtkFunctionType::KeyMatch5:
+ func = std::make_shared<ExprtkMatchFunction>(idenfier,
KeyMatch5);
+ break;
case ExprtkFunctionType::IpMatch:
func = std::make_shared<ExprtkMatchFunction>(idenfier,
IPMatch);
break;
diff --git a/include/casbin/util/built_in_functions.h
b/include/casbin/util/built_in_functions.h
index abb2d1d..12f53af 100644
--- a/include/casbin/util/built_in_functions.h
+++ b/include/casbin/util/built_in_functions.h
@@ -53,6 +53,11 @@ std::string KeyGet3(const std::string& key1, const
std::string& key2, const std:
// But KeyMatch3 will match both.
bool KeyMatch4(const std::string& key1, const std::string& key2);
+// KeyMatch5 determines whether key1 matches the pattern of key2 (similar to
RESTful path), key2 can contain a *.
+// The query string in key1 is ignored.
+// For example, "/foo/bar?status=1&type=2" matches "/foo/bar",
"/parent/child1" matches "/parent/*" and "/parent/{id}"
+bool KeyMatch5(const std::string& key1, const std::string& key2);
+
// RegexMatch determines whether key1 matches the pattern of key2 in regular
expression.
bool RegexMatch(const std::string& key1, const std::string& key2);
diff --git a/tests/built_in_functions_test.cpp
b/tests/built_in_functions_test.cpp
index 72bc6d2..b536f2a 100644
--- a/tests/built_in_functions_test.cpp
+++ b/tests/built_in_functions_test.cpp
@@ -282,6 +282,53 @@ TEST(TestBuiltInFunctions, TestKeyMatch4) {
TestKeyMatch4Fn("/parent/123/child/123", "/parent/{i/d}/child/{i/d}",
false);
}
+void TestKeyMatch5Fn(std::string key1, std::string key2, bool res) {
+ auto evaluator = casbin::ExprtkEvaluator();
+ auto func =
casbin::ExprtkFunctionFactory::GetExprtkFunction(casbin::ExprtkFunctionType::KeyMatch5,
2);
+ evaluator.AddFunction("keyMatch5", func);
+ evaluator.AddIdentifier("key1", key1);
+ evaluator.AddIdentifier("key2", key2);
+ evaluator.Eval("keyMatch5(key1, key2)");
+ bool my_res = evaluator.GetBoolean();
+ EXPECT_EQ(res, my_res);
+}
+
+TEST(TestBuiltInFunctions, TestKeyMatch5) {
+ TestKeyMatch5Fn("/parent/child?status=1&type=2", "/parent/child", true);
+ TestKeyMatch5Fn("/parent?status=1&type=2", "/parent/child", false);
+
+ TestKeyMatch5Fn("/parent/child/?status=1&type=2", "/parent/child/", true);
+ TestKeyMatch5Fn("/parent/child/?status=1&type=2", "/parent/child", false);
+ TestKeyMatch5Fn("/parent/child?status=1&type=2", "/parent/child/", false);
+
+ TestKeyMatch5Fn("/foo", "/foo", true);
+ TestKeyMatch5Fn("/foo", "/foo*", true);
+ TestKeyMatch5Fn("/foo", "/foo/*", false);
+ TestKeyMatch5Fn("/foo/bar", "/foo", false);
+ TestKeyMatch5Fn("/foo/bar", "/foo*", false);
+ TestKeyMatch5Fn("/foo/bar", "/foo/*", true);
+ TestKeyMatch5Fn("/foobar", "/foo", false);
+ TestKeyMatch5Fn("/foobar", "/foo*", false);
+ TestKeyMatch5Fn("/foobar", "/foo/*", false);
+
+ TestKeyMatch5Fn("/", "/{resource}", false);
+ TestKeyMatch5Fn("/resource1", "/{resource}", true);
+ TestKeyMatch5Fn("/myid", "/{id}/using/{resId}", false);
+ TestKeyMatch5Fn("/myid/using/myresid", "/{id}/using/{resId}", true);
+
+ TestKeyMatch5Fn("/proxy/myid", "/proxy/{id}/*", false);
+ TestKeyMatch5Fn("/proxy/myid/", "/proxy/{id}/*", true);
+ TestKeyMatch5Fn("/proxy/myid/res", "/proxy/{id}/*", true);
+ TestKeyMatch5Fn("/proxy/myid/res/res2", "/proxy/{id}/*", true);
+ TestKeyMatch5Fn("/proxy/myid/res/res2/res3", "/proxy/{id}/*", true);
+ TestKeyMatch5Fn("/proxy/", "/proxy/{id}/*", false);
+
+ TestKeyMatch5Fn("/proxy/myid?status=1&type=2", "/proxy/{id}/*", false);
+ TestKeyMatch5Fn("/proxy/myid/res?status=1&type=2", "/proxy/{id}/*", true);
+ TestKeyMatch5Fn("/proxy/myid/res/res2?status=1&type=2", "/proxy/{id}/*",
true);
+ TestKeyMatch5Fn("/proxy/myid/res/res2/res3?status=1&type=2",
"/proxy/{id}/*", true);
+}
+
void TestRegexMatchFn(std::string key1, std::string key2, bool res) {
auto evaluator = casbin::ExprtkEvaluator();
auto func =
casbin::ExprtkFunctionFactory::GetExprtkFunction(casbin::ExprtkFunctionType::RegexMatch,
2);
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]