需求:
準入授權(quán)配置文件有時候分了好幾個維度進行配置,例如 company|product|sys這種格式的配置:
1.配置 "sina|weibo|pusher" 表示 sina公司weibo產(chǎn)品pusher系統(tǒng)能夠準入,而"sina|weibo|sign"不允許準入
2.配置 "sina|*|pusher” 表示sina公司所有產(chǎn)品的pusher系統(tǒng)都能夠準入
3.配置 “*|*|pusher” 表示所有公司的所有產(chǎn)品的pusher系統(tǒng)都能夠準入
…
類似還有很多場景,好了,簡單的東西不扯蛋了.
實現(xiàn):
面對這個需求我第一時間想的是如何設(shè)計模式串,如何快速實現(xiàn)功能,因為我現(xiàn)在寫的是一個C服務(wù),所以我首先出現(xiàn)在我腦海的是一大堆strchr(XXX, ‘*'), strchr(XXX, ‘|')等等東西,后面發(fā)現(xiàn)這個東西沒有必要自己造輪子,有現(xiàn)成的函數(shù)可以用,那就是fnmatch.
google了一下,發(fā)現(xiàn)fnmatch的資料并不是很多,大部分還都是講php函數(shù)的,所以沒辦法,只能自己寫寫測測了.
#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|*"},    //不能被匹配的    {"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_PATHNAME);      if(FNM_NOMATCH == ret){        cout<<"sorry I'm failed ["<< vec_str.at(i) <<"]"<<endl;      }       }       ++z;    }}結(jié)果:
實驗一把,結(jié)果還不賴,完全滿足需求:

需求滿足了,我擔心的還有一個問題,那就是性能,注釋掉cout輸出,將while z語句調(diào)至1,000,000,重新編譯跑一下:
time ./fnmatch

看來效率還不錯,2.1s 進行了100W次匹配,平均2us一次,性能要求也滿足了...
附:上面文章只介紹了在Linux系統(tǒng)下直接調(diào)用系統(tǒng)函數(shù)fnmatch即可實現(xiàn),而沒有考慮在Windows在的使用。
本人這周看了下Google-glog代碼,恰巧發(fā)現(xiàn)了一個類似fnmatch的簡單實現(xiàn),因此綜合起來提供了一個跨平臺的接口。
#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;  }}/**注意:Windows平臺下尚未實現(xiàn)最后一個參數(shù)flags的功能!!!*/int fnmatch_win(const char *pattern, const char *name, int flags = 0){  if(SafeFNMatch(pattern,strlen(pattern),name,strlen(name)))    return 0;  else    return FNM_NOMATCH;}#else#include <fnmatch.h>#endifint main(){  const char* orgin_str = "sina|weibo|pusher";  char pattern_arr[][20] = {    {"sina|*|pusher"},    {"sina|*|*"},    {"*|weibo|*"},    //不能被匹配的    {"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/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;}輸出如下:

新聞熱點
疑難解答