34
34
35
35
namespace casbin {
36
36
37
+ namespace {
38
+ static const std::regex capturingColonNonSlashRegex (" (.*?):[^/]+(.*?)" );
39
+ static const std::regex enclosedPlaceHolderRegex (" (.*?)\\ {[^/]+?\\ }(.*?)" );
40
+
41
+ std::string PrepareWildCardMatching (const std::string& value) {
42
+ static const std::regex pattern (" /\\ *" );
43
+ return std::regex_replace (value, pattern, " /.*" );
44
+ }
45
+
46
+ std::string EscapeCurlyBraces (const std::string& value) {
47
+ static const std::regex curlyBraceOpenPattern (" \\ {" );
48
+ static const std::regex curlyBraceClosePattern (" \\ }" );
49
+
50
+ std::string intermediate = std::regex_replace (value, curlyBraceOpenPattern, " \\ {" );
51
+ return std::regex_replace (intermediate, curlyBraceClosePattern, " \\ }" );
52
+ }
53
+ }
54
+
37
55
// KeyMatch determines whether key1 matches the pattern of key2 (similar to RESTful path), key2 can contain a *.
38
56
// For example, "/foo/bar" matches "/foo/*"
39
57
bool KeyMatch (const std::string& key1, const std::string& key2) {
@@ -67,10 +85,9 @@ std::string KeyGet(const std::string& key1, const std::string& key2) {
67
85
// KeyMatch2 determines whether key1 matches the pattern of key2 (similar to RESTful path), key2 can contain a *.
68
86
// For example, "/foo/bar" matches "/foo/*", "/resource1" matches "/:resource"
69
87
bool KeyMatch2 (const std::string& key1, const std::string& key2) {
70
- std::string k2 = regex_replace (key2, std::regex (" /\\ *" ), " /.*" );
71
- k2 = regex_replace (k2, std::regex (" (.*?):[^/]+(.*?)" ), " $1[^/]+$2" );
72
- k2 = regex_replace (k2, std::regex (" \\ {" ), " \\ {" );
73
- k2 = regex_replace (k2, std::regex (" \\ }" ), " \\ }" );
88
+ std::string k2 = PrepareWildCardMatching (key2);
89
+ k2 = std::regex_replace (k2, capturingColonNonSlashRegex, " $1[^/]+$2" );
90
+ k2 = EscapeCurlyBraces (k2);
74
91
75
92
if (!k2.compare (" *" ))
76
93
k2 = " (.*)" ;
@@ -82,17 +99,16 @@ bool KeyMatch2(const std::string& key1, const std::string& key2) {
82
99
// For example, "/resource1" matches "/:resource"
83
100
// if the path_var == "resource", then "resource1" will be returned
84
101
std::string KeyGet2 (const std::string& key1, const std::string& key2, const std::string& path_var) {
85
- std::string k2 = regex_replace (key2, std::regex (" /\\ *" ), " /.*" );
102
+ static const std::regex colonAnyButSlashPattern (" :[^/]+" );
103
+ std::string k2 = PrepareWildCardMatching (key2);
86
104
87
105
std::vector<std::string> keys;
88
- std::regex keys_regex (" :[^/]+" );
89
- for (std::sregex_iterator it (k2.begin (), k2.end (), keys_regex), end_it; it != end_it; ++it) {
106
+ for (std::sregex_iterator it (k2.begin (), k2.end (), colonAnyButSlashPattern), end_it; it != end_it; ++it) {
90
107
keys.push_back (it->str ());
91
108
}
92
109
93
- k2 = regex_replace (k2, std::regex (" (.*?):[^/]+(.*?)" ), " $1([^/]+)$2" );
94
- k2 = regex_replace (k2, std::regex (" \\ {" ), " \\ {" );
95
- k2 = regex_replace (k2, std::regex (" \\ }" ), " \\ }" );
110
+ k2 = std::regex_replace (k2, capturingColonNonSlashRegex, " $1([^/]+)$2" );
111
+ k2 = EscapeCurlyBraces (k2);
96
112
if (!k2.compare (" *" ))
97
113
k2 = " (.*)" ;
98
114
k2 = " ^" + k2 + " $" ;
@@ -110,10 +126,9 @@ std::string KeyGet2(const std::string& key1, const std::string& key2, const std:
110
126
// KeyMatch3 determines whether key1 matches the pattern of key2 (similar to RESTful path), key2 can contain a *.
111
127
// For example, "/foo/bar" matches "/foo/*", "/resource1" matches "/{resource}"
112
128
bool KeyMatch3 (const std::string& key1, const std::string& key2) {
113
- std::string k2 = regex_replace (key2, std::regex (" /\\ *" ), " /.*" );
114
- k2 = regex_replace (k2, std::regex (" (.*?)\\ {[^/]+?\\ }(.*?)" ), " $1[^/]+$2" );
115
- k2 = regex_replace (k2, std::regex (" \\ {" ), " \\ {" );
116
- k2 = regex_replace (k2, std::regex (" \\ }" ), " \\ }" );
129
+ std::string k2 = PrepareWildCardMatching (key2);
130
+ k2 = std::regex_replace (k2, enclosedPlaceHolderRegex, " $1[^/]+$2" );
131
+ k2 = EscapeCurlyBraces (k2);
117
132
118
133
return RegexMatch (key1, " ^" + k2 + " $" );
119
134
}
@@ -122,17 +137,16 @@ bool KeyMatch3(const std::string& key1, const std::string& key2) {
122
137
// For example, "project/proj_project1_admin/" matches "project/proj_{project}_admin/"
123
138
// if the pathVar == "project", then "project1" will be returned
124
139
std::string KeyGet3 (const std::string& key1, const std::string& key2, const std::string& path_var) {
125
- std::string k2 = regex_replace (key2, std::regex (" /\\ *" ), " /.*" );
140
+ static const std::regex placeHolderPattern (" \\ {[^/]+?\\ }" );
141
+ std::string k2 = PrepareWildCardMatching (key2);
126
142
127
143
std::vector<std::string> keys;
128
- std::regex keys_regex (" \\ {[^/]+?\\ }" );
129
- for (std::sregex_iterator it (k2.begin (), k2.end (), keys_regex), end_it; it != end_it; ++it) {
144
+ for (std::sregex_iterator it (k2.begin (), k2.end (), placeHolderPattern), end_it; it != end_it; ++it) {
130
145
keys.push_back (it->str ());
131
146
}
132
147
133
- k2 = regex_replace (k2, std::regex (" (.*?)\\ {[^/]+?\\ }(.*?)" ), " $1([^/]+?)$2" );
134
- k2 = regex_replace (k2, std::regex (" \\ {" ), " \\ {" );
135
- k2 = regex_replace (k2, std::regex (" \\ }" ), " \\ }" );
148
+ k2 = std::regex_replace (k2, enclosedPlaceHolderRegex, " $1([^/]+?)$2" );
149
+ k2 = EscapeCurlyBraces (k2);
136
150
if (!k2.compare (" *" ))
137
151
k2 = " (.*)" ;
138
152
k2 = " ^" + k2 + " $" ;
@@ -153,16 +167,15 @@ std::string KeyGet3(const std::string& key1, const std::string& key2, const std:
153
167
// "/parent/123/child/456" does not match "/parent/{id}/child/{id}"
154
168
// But KeyMatch3 will match both.
155
169
bool KeyMatch4 (const std::string& key1, const std::string& key2) {
156
- std::string k2 = regex_replace (key2, std::regex ( " / \\ * " ), " /.* " );
170
+ std::string k2 = PrepareWildCardMatching (key2);
157
171
158
172
std::vector<std::string> tokens;
159
- std::regex tokens_regex (" \\ {([^/]+)\\ }" );
173
+ static std::regex tokens_regex (" \\ {([^/]+)\\ }" );
160
174
for (std::sregex_iterator it (k2.begin (), k2.end (), tokens_regex), end_it; it != end_it; ++it)
161
175
tokens.push_back (it->str ());
162
176
163
- k2 = regex_replace (k2, std::regex (" (.*?)\\ {[^/]+?\\ }(.*?)" ), " $1([^/]+)$2" );
164
- k2 = regex_replace (k2, std::regex (" \\ {" ), " \\ {" );
165
- k2 = regex_replace (k2, std::regex (" \\ }" ), " \\ }" );
177
+ k2 = std::regex_replace (k2, enclosedPlaceHolderRegex, " $1([^/]+)$2" );
178
+ k2 = EscapeCurlyBraces (k2);
166
179
k2 = " ^" + k2 + " $" ;
167
180
std::smatch matches;
168
181
std::regex_match (key1.begin (), key1.end (), matches, std::regex (k2));
@@ -187,7 +200,7 @@ bool KeyMatch4(const std::string& key1, const std::string& key2) {
187
200
// RegexMatch determines whether key1 matches the pattern of key2 in regular expression.
188
201
bool RegexMatch (const std::string& key1, const std::string& key2) {
189
202
std::regex regex_s (key2);
190
- return regex_match (key1, regex_s);
203
+ return std:: regex_match (key1, regex_s);
191
204
}
192
205
193
206
// IPMatch determines whether IP address ip1 matches the pattern of IP address ip2, ip2 can be an IP address or a CIDR pattern.
0 commit comments