1 /*
2  * File:  GlobMatcher.cpp
3  *
4  * Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
5  * See included license file for license details.
6  */
7 
8 #include "GlobMatcher.h"
9 
10 #ifndef NEGATE
11 #define NEGATE      '^'                           // std cset negation char
12 #endif
13 
14 using namespace elftosb;
15 
16 //! The glob pattern must match the \e entire test value argument in order
17 //! for the match to be considered successful. Thus, even if, for example,
18 //! the pattern matches all but the last character the result will be false.
19 //!
20 //! \retval true The test value does match the glob pattern.
21 //! \retval false The test value does not match the glob pattern.
match(const std::string & testValue)22 bool GlobMatcher::match(const std::string & testValue)
23 {
24           return globMatch(testValue.c_str(), m_pattern.c_str());
25 }
26 
27 //! \note This glob implementation was originally written by ozan s. yigit in
28 //!                 December 1994. This is public domain source code.
globMatch(const char * str,const char * p)29 bool GlobMatcher::globMatch(const char *str, const char *p)
30 {
31           int negate;
32           int match;
33           int c;
34 
35           while (*p) {
36                     if (!*str && *p != '*')
37                               return false;
38 
39                     switch (c = *p++) {
40 
41                     case '*':
42                               while (*p == '*')
43                                         p++;
44 
45                               if (!*p)
46                                         return true;
47 
48                               if (*p != '?' && *p != '[' && *p != '\\')
49                                         while (*str && *p != *str)
50                                                   str++;
51 
52                               while (*str) {
53                                         if (globMatch(str, p))
54                                                   return true;
55                                         str++;
56                               }
57                               return false;
58 
59                     case '?':
60                               if (*str)
61                                         break;
62                               return false;
63 
64                     // set specification is inclusive, that is [a-z] is a, z and
65                     // everything in between. this means [z-a] may be interpreted
66                     // as a set that contains z, a and nothing in between.
67                     case '[':
68                               if (*p != NEGATE)
69                                         negate = false;
70                               else {
71                                         negate = true;
72                                         p++;
73                               }
74 
75                               match = false;
76 
77                               while (!match && (c = *p++)) {
78                                         if (!*p)
79                                                   return false;
80                                         if (*p == '-') {    // c-c
81                                                   if (!*++p)
82                                                             return false;
83                                                   if (*p != ']') {
84                                                             if (*str == c || *str == *p ||
85                                                                 (*str > c && *str < *p))
86                                                                       match = true;
87                                                   }
88                                                   else {              // c-]
89                                                             if (*str >= c)
90                                                                       match = true;
91                                                             break;
92                                                   }
93                                         }
94                                         else {                        // cc or c]
95                                                   if (c == *str)
96                                                             match = true;
97                                                   if (*p != ']') {
98                                                             if (*p == *str)
99                                                                       match = true;
100                                                   }
101                                                   else
102                                                             break;
103                                         }
104                               }
105 
106                               if (negate == match)
107                                         return false;
108                               // if there is a match, skip past the cset and continue on
109                               while (*p && *p != ']')
110                                         p++;
111                               if (!*p++)          // oops!
112                                         return false;
113                               break;
114 
115                     case '\\':
116                               if (*p)
117                                         c = *p++;
118                     default:
119                               if (c != *str)
120                                         return false;
121                               break;
122 
123                     }
124                     str++;
125           }
126 
127           return !*str;
128 }
129 
130