Demand:
Access authorization profiles are sometimes configured in several dimensions, such as Company|product|sys configuration in this format:
1. Configuration "Sina|weibo|pusher" means that Sina company Weibo product Pusher system can access, and "Sina|weibo|sign" does not allow access
2. Configuration "Sina|*|pusher" means that the pusher system of all products of Sina Company can access
3. The configuration "*|*|pusher" means that all pusher systems of all products of the company are able to access
...
There are a lot of scenes like this, okay, simple things don't pull the eggs.
Realize:
In the face of this demand I think the first time is how to design the pattern string, how to quickly implement the function, because I now write a C service, so I first out of my mind is a lot of strchr (XXX, ' * '), STRCHR (xxx, ' | ') And so on, later found that this thing is not necessary to build their own wheels, there are ready-made functions can be used, that is fnmatch.
Google a bit, found that Fnmatch is not a lot of information, most of them are talking about PHP functions, so there is no way, can only write their own test.
#include <iostream>
#include <fnmatch.h>
#include <vector>
using namespace std;
int main ()
{
const char* ORGIN_STR = "Sina|weibo|pusher";
Char pattern_arr[][20] = {"
sina|*|pusher"},
{"sina|*|*"},
{"*|weibo|*"},
///cannot be matched
{"Sina" |pic|* "}, {" *|*|sign "}, {" *|weibo|sign "}, {" *|pic|sign "}, {
" Sina|pic|sign "},
{" *|*|* " }
};
static int pattern_arr_size = sizeof (Pattern_arr)/sizeof (pattern_arr[0));
Vector<char *> vec_str;
for (int i = 0; i < pattern_arr_size i + +)
{
vec_str.push_back (pattern_arr[i]);
}
int ret;
int z = 0;
while (Z < 1) {
for (int i = 0; i < vec_str.size (); i++)
{
ret = Fnmatch (vec_str.at (i), Orgin_str, fnm_p Athname);
if (Fnm_nomatch = = ret) {
cout<< "sorry I ' m failed [" << vec_str.at (I) << "]" <<endl;
}
}
++z}
}
Results:
Experiment one, the results are not bad, fully meet the needs:
The requirements are met, and I'm worried about a problem, which is performance, commenting out the cout output, and then tuning the while Z statement to 1,000,000 and recompiling and running:
Time./fnmatch
Seems to be a good efficiency, 2.1s 100W time matching, the average 2us once, performance requirements are met ...
Attached: The above article only describes the Linux system directly invoke the system function Fnmatch can be implemented, without considering the use of Windows.
I looked at the next Google-glog code this week, happened to find a similar fnmatch simple implementation, so combined to provide a cross-platform interface.
#ifdef os_windows/* Bits set in the FLAGS argument to ' Fnmatch '. Copy from FNMATCH.H (Linux)/#define FNM_PATHNAME (1 << 0)/* No wildcard can ever match '/'. * * #define FNM_NOESCAPE (1 << 1)/* backslashes don ' t quote special chars. */#define FNM_PERIOD (1 << 2 )/* leading '. ' is matched only explicitly. * * #define FNM_NOMATCH 1 #define Fnmatch Fnmatch_win/**copy from google-glog*/bool Safefnmatch (const char* pattern
, size_t patt_len,const char* str,size_t str_len) {size_t p = 0;
size_t s = 0;
while (1) {if (p = = Patt_len && s = = Str_len) return true;
if (p = = Patt_len) return false;
if (s = = Str_len) return p+1 = = Patt_len && pattern[p] = = ' * ';
if (pattern[p] = = Str[s] | | | pattern[p] = = '? ')
{p = 1;
s + + 1;
Continue
} if (pattern[p] = = ' * ') {if (p+1 = = Patt_len) return true; do {if (Safefnmatch pattern+ (p+1), patt_len-(p+1),Str+s, Str_len-s)) {return true;
} s + + 1;
while (S!= str_len);
return false;
return false; }/** Note: The function of the last parameter flags is not yet implemented under the Windows platform!!! */int Fnmatch_win (const char *pattern, const char *name, int flags = 0) {if (Safefnmatch Pattern,strlen (pattern), name,s
Trlen (name)) return 0;
else return fnm_nomatch;
#else #include <fnmatch.h> #endif int main () {const char* ORGIN_STR = "Sina|weibo|pusher";
Char pattern_arr[][20] = {"Sina|*|pusher"}, {"sina|*|*"}, {"*|weibo|*"},///cannot be matched {"sina|pic|*"},
{"*|*|sign"}, {"*|weibo|sign"}, {"*|pic|sign"}, {"Sina|pic|sign"}, {"*|*|*"}};
static int pattern_arr_size = sizeof (Pattern_arr)/sizeof (pattern_arr[0));
Vector<char *> Vec_str;
for (int i = 0; i < pattern_arr_size i + +) {Vec_str.push_back (pattern_arr[i]);
} std::cout << "Origin Str:" << orgin_str << "\ n";
int ret;for (int i = 0; i < vec_str.size (); i++) {ret = Fnmatch (vec_str.at (i), orgin_str, fnm_pathname);
if (ret = = Fnm_nomatch) {cout<< "Sorry, I ' m failed: [" << vec_str.at (i) << "]\n";
else {cout<< "OK, I ' m success: [" << vec_str.at (i) << "]\n";
} return 0;
}
The output is as follows: