Changeset 1098


Ignore:
Timestamp:
Jun 13, 2010, 6:46:29 PM (11 years ago)
Author:
Peter Johansson
Message:

closes #450. extend filename matching tp allow [xyz] and ?. Also fixed a bug when having asterisk (*) in end of pattern string

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/lib/Configuration.cc

    r1097 r1098  
    366366    std::string res;
    367367    std::vector<std::string> vec;
    368     if (!regexp(str.begin(), str.end(), dic.first.begin(),dic.first.end(),vec)){
     368    if (!regexp(dic.first, str, vec)) {
    369369      std::stringstream mess;
    370370      mess << "invalid config file: "
  • trunk/lib/utility.cc

    r1097 r1098  
    158158  bool fnmatch(const std::string& pattern, const std::string& str)
    159159  {
    160     int res = ::fnmatch(pattern.c_str(), str.c_str(), FNM_PERIOD);
     160    int res = ::fnmatch(pattern.c_str(), str.c_str(), 0);
    161161    if (res==0)
    162162      return true;
     
    223223
    224224
    225   bool regexp(std::string::const_iterator first1,
    226               std::string::const_iterator last1,
    227               std::string::const_iterator first2,
    228               std::string::const_iterator last2,
     225  bool regexp(const std::string& pattern, const std::string& str,
    229226              std::vector<std::string>& vec)
    230227  {
    231     if (vec.empty())
    232       vec.push_back("");
    233 
    234     // first two cases when ranges are empty
    235     if (first1==last1 && first2==last2){
    236       vec.pop_back();
    237       return true;
    238     }
     228    bool regexp__(std::string::const_iterator first1,
     229                  std::string::const_iterator last1,
     230                  std::string::const_iterator first2,
     231                  std::string::const_iterator last2,
     232                  std::vector<std::string>::iterator item);
     233   
     234    // find number of special chars
     235    size_t count=0;
     236    for (std::string::const_iterator i=pattern.begin(); i!=pattern.end(); ++i)
     237      if (*i=='*' || *i=='?' || *i=='[')
     238        ++count;
     239    vec.resize(count);
     240    return regexp__(pattern.begin(), pattern.end(), str.begin(), str.end(),
     241                    vec.begin());
     242  }
     243
     244  bool regexp__(std::string::const_iterator first1,
     245                std::string::const_iterator last1,
     246                std::string::const_iterator first2,
     247                std::string::const_iterator last2,
     248                std::vector<std::string>::iterator item)
     249  {
     250    if (first1==last1) {
     251      return first2==last2;
     252    }
     253    if (*first1 == '*') {
     254      if (first2<last2) {
     255        item->push_back(*first2);
     256        if (regexp__(first1, last1, first2+1, last2, item))
     257          return true;
     258        item->resize(item->size()-1);
     259      }
     260      return regexp__(first1+1, last1, first2, last2, item+1);
     261    }
     262    if (*first1 == '?') {
     263      if (first2==last2)
     264        return false;
     265      *item = *first2;
     266      return regexp__(first1+1, last1, first2+1, last2, item+1);
     267    }
     268    if (*first1 == '[') {
     269      if (first2==last2)
     270        return false;
     271      bool found = false;
     272      while (*first1 != ']') {
     273        if (*first1 == *first2) {
     274          found = true;
     275          *item = *first2;
     276        }
     277        ++first1;
     278        assert(first1!=last1);
     279      }
     280      return regexp__(first1+1, last1, first2+1, last2, item+1);
     281      /*
     282      while (*first2 != ']') {
     283        if (*first2==*first1) {
     284          found = true;
     285          vec.back() = *first1;
     286          vec.push_back("");
     287        }
     288        ++first2;
     289        assert(first2!=last2);
     290      }
     291      if (!found)
     292        return false;
     293      return regexp(first1+1, last1, first2+1, last2, vec);
     294      */
     295    }
     296
     297    if (first2==last2)
     298      return false;
     299    if (*first1 != *first2)
     300      return false;
     301    return regexp__(first1+1, last1, first2+1, last2, item);
     302
     303    /*
     304
     305
     306
     307    if (first1==last1)
     308      return false;
     309    if (*first1 != *first2)
     310      return false;
     311    return regexp(first1+1, last1, first2+1, last2, vec);
     312   
     313    /// hm
    239314    if (first1==last1 || first2==last2)
    240315      return false;
     
    274349      return false;
    275350    return regexp(++first1, last1, ++first2, last2, vec);
     351    */
    276352  }
    277353
  • trunk/lib/utility.h

    r1090 r1098  
    165165
    166166  /**
    167      \return true if first range match second range
    168 
    169      Second range may contain wildcards (such as '*' and '?'), in
    170      which case vector \a vec is filled with the corresponding strings
    171      in first range. The algorithm is greedy, i.e., wildcard * is will
     167     \return true if \a str matches \a pattern
     168
     169     \a pattern may contain wildcards '*', '?' and \a vec will contain
     170     the matching string in \a str. If it's not a match, \a vec is
     171     undefined. The algorithm is greedy, i.e., wildcards '*' will
    172172     consume as many charcters as possible.
    173173
    174174     \note \a vec is supposed to be empty
    175175   */
    176   bool regexp(std::string::const_iterator first1,
    177               std::string::const_iterator end1,
    178               std::string::const_iterator first2,
    179               std::string::const_iterator end2,
     176  bool regexp(const std::string& pattern, const std::string& str,
    180177              std::vector<std::string>& vec);
    181178
  • trunk/test/utility_test.cc

    r1096 r1098  
    4343  ok &= test_fnmatch(true,"peter", "peter");
    4444  ok &= test_fnmatch(false,"peter", "peterj");
     45
     46  ok &= test_fnmatch(true,"*", "peterj");
    4547  ok &= test_fnmatch(true,"p*", "peterj");
    4648  ok &= test_fnmatch(true, "p*", "peter");
    4749  ok &= test_fnmatch(false, "p*j", "peter");
     50  ok &= test_fnmatch(true, "p*j", "peterj");
    4851  ok &= test_fnmatch(true, "*peter", "peter");
     52
     53  ok &= test_fnmatch(true, "p?ter", "peter");
     54  ok &= test_fnmatch(false, "p?er", "peter");
     55  ok &= test_fnmatch(false, "p?eter", "peter");
    4956
    5057  ok &= test_fnmatch(true, "filename", "filename");
    5158  ok &= test_fnmatch(true, "*name", "filename");
    5259  ok &= test_fnmatch(true, "[fa]il?name", "filename");
     60  ok &= test_fnmatch(true, "[fa]*il?name", "ffilename");
     61
     62  ok &= test_fnmatch(true, "[fa]*il?name", "fafafailename");
     63  ok &= test_fnmatch(false, "[fa]?il?name", "ilename");
     64  ok &= test_fnmatch(false, "?[fa]il?name", "ilename");
     65  ok &= test_fnmatch(true, "[fa]il?name", "filename");
     66  ok &= test_fnmatch(false, "[fa]?il?name", "fafafailename");
     67
    5368  ok &= test_fnmatch(true, "*name", "/path/to/filename");
    5469  ok &= test_fnmatch(true, "*name", "file.name");
    55   // posix dictates that leading persion can not be matched by wildcard
    56   ok &= test_fnmatch(false, "*.txt", ".file.txt");
     70  // posix dictates that leading period can not be matched by
     71  // wildcard, but here we allow match
     72  ok &= test_fnmatch(true, "*.txt", ".file.txt");
     73
    5774
    5875  std::vector<std::string> vec;
    5976  ok &= test_regexp(true,"abcde", "abcde", vec);
     77  vec.push_back("c");
     78  ok &= test_regexp(true,"ab?de", "abcde", vec);
     79  vec[0] = "bcd";
     80  ok &= test_regexp(true,"a*e", "abcde", vec);
    6081  vec.push_back("");
    61   ok &= test_regexp(true,"abcde", "abcd?e", vec);
    62   vec[0]="c";
    63   ok &= test_regexp(true,"abcde", "ab?de", vec);
    64   vec[0] = "bcd";
    65   ok &= test_regexp(true,"abcde", "a*e", vec);
    66   vec.push_back("");
    67   ok &= test_regexp(true,"abcddf", "a*d*f", vec);
     82  ok &= test_regexp(true,"a*d*f", "abcddf", vec);
    6883  vec[0] = "bc";
    6984  vec[1] = "ef";
    70   ok &= test_regexp(true,"abcdefg", "a*d*g", vec);
     85  ok &= test_regexp(true,"a*d*g", "abcdefg", vec);
    7186  vec.push_back("");
    72   ok &= test_regexp(true,"abcdefg", "a*d*?g", vec);
    7387  vec[1]="e";
    7488  vec[2]="f";
    75   ok &= test_regexp(true,"abcdefg", "a*d??g", vec);
     89  ok &= test_regexp(true,"a*d*?g", "abcdefg", vec);
     90  ok &= test_regexp(true,"a*d??g", "abcdefg", vec);
     91  vec.resize(2);
     92  vec[0]="f";
     93  vec[1]="e";
     94  ok &= test_regexp(true, "[fa]il?name", "filename", vec);
    7695
    7796  if (ok)
     
    84103  using namespace theplu::svndigest;
    85104  bool res = fnmatch(a.c_str(), b.c_str());
    86   if (res == answ)
     105  // check that fnmatch and regexp agree
     106  std::vector<std::string> v;
     107  bool res2 = regexp(a, b, v);
     108  if (res == answ && res2==answ)
    87109    return true;
    88   std::cerr << "fnmatch(" << a << ", " << b << ") results "
    89             << res
    90             << ". Expects " << answ << std::endl;
     110  if (res!=answ)
     111    std::cerr << "fnmatch(" << a << ", " << b << ") results "
     112              << res
     113              << ". Expects " << answ << std::endl;
     114  if (res2!=answ)
     115    std::cerr << "regexp(" << b << ", " << a << ") results "
     116              << res2
     117              << ". Expects " << answ << std::endl;
    91118  return false;
    92119}
     
    107134  using namespace theplu::svndigest;
    108135  std::vector<std::string> v;
    109   bool res = regexp(a.begin(), a.end(), b.begin(), b.end(), v);
     136  bool res = regexp(a, b, v);
    110137  if (res!=ans || v!=vec) {
    111138    std::cerr << "regexp(" << a << ", " << b << ") results "
Note: See TracChangeset for help on using the changeset viewer.