Field3D
PatternMatch.cpp
Go to the documentation of this file.
1 //----------------------------------------------------------------------------//
2 
3 /*
4  * Copyright (c) 2009 Sony Pictures Imageworks Inc
5  *
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the
17  * distribution. Neither the name of Sony Pictures Imageworks nor the
18  * names of its contributors may be used to endorse or promote
19  * products derived from this software without specific prior written
20  * permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
33  * OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 //----------------------------------------------------------------------------//
37 
42 //----------------------------------------------------------------------------//
43 
44 // Header include
45 #include "PatternMatch.h"
46 
47 // System includes
48 #ifdef WIN32
49 #include "Shlwapi.h"
50 #define FNM_NOMATCH 1
51 #define FNM_NOESCAPE 0
52 #else
53 #include <fnmatch.h>
54 #endif
55 
56 //----------------------------------------------------------------------------//
57 
59 
60 //----------------------------------------------------------------------------//
61 // Function implementations
62 //----------------------------------------------------------------------------//
63 
64 #ifdef WIN32
65 static int
66 fnmatch(const char *pattern, const char *string, int /*flags*/)
67 {
68  return PathMatchSpec(string, pattern) ? 0 : FNM_NOMATCH;
69 }
70 #endif
71 
72 //----------------------------------------------------------------------------//
73 
74 std::vector<std::string>
75 split(const std::string &s)
76 {
77  return split(s, " ");
78 }
79 
80 //----------------------------------------------------------------------------//
81 
82 std::vector<std::string>
83 split(const std::string &s, const std::string &separatorChars)
84 {
85  typedef boost::char_separator<char> CharSeparator;
86  typedef boost::tokenizer<CharSeparator> Tokenizer;
87 
88  std::vector<std::string> result;
89  CharSeparator separators(separatorChars.c_str());
90  Tokenizer tokenizer(s, separators);
91 
92  BOOST_FOREACH (const std::string &i, tokenizer) {
93  result.push_back(i);
94  }
95 
96  return result;
97 }
98 
99 //------------------------------------------------------------------------------
100 
101 bool
102 match(const std::string &name, const std::string &attribute,
103  const std::vector<std::string> &patterns,
104  const MatchFlags flags)
105 {
106  bool foundMatch = false;
107  bool foundExclusion = false;
108 
109  if (patterns.size() == 0) {
110  return flags && MatchEmptyPattern;
111  }
112 
113  BOOST_FOREACH (const std::string &i, patterns) {
114 
115  if (i.size() == 0) {
116  continue;
117  }
118 
119  // Check exclusion string
120  bool isExclusion = i[0] == '-' || i[0] == '^';
121  // Update string
122  const std::string pattern = isExclusion ? i.substr(1) : i;
123 
124  // String to match
125  std::string s;
126 
127  // Determine type of matching
128  if (pattern.find(":") != std::string::npos) {
129  // Pattern includes separator. Match against name:attribute
130  s = name + ":" + attribute;
131  } else {
132  // No separator. Just match against attribute
133  s = attribute;
134  }
135 
136  // Match with wildcards
137  if (fnmatch(pattern.c_str(), s.c_str(), FNM_NOESCAPE) == 0) {
138  if (isExclusion) {
139  foundExclusion = true;
140  } else {
141  foundMatch = true;
142  }
143  }
144 
145  }
146 
147  return foundMatch && !foundExclusion;
148 }
149 
150 //------------------------------------------------------------------------------
151 
152 bool
153 match(const std::string &name, const std::string &attribute,
154  const std::string &patterns,
155  const MatchFlags flags)
156 {
157  return match(name, attribute, split(patterns), flags);
158 }
159 
160 //------------------------------------------------------------------------------
161 
162 bool
163 match(const std::string &attribute, const std::vector<std::string> &patterns,
164  const MatchFlags flags)
165 {
166  bool foundMatch = false;
167  bool foundExclusion = false;
168 
169  if (patterns.size() == 0) {
170  return flags && MatchEmptyPattern;
171  }
172 
173  BOOST_FOREACH (const std::string &i, patterns) {
174 
175  if (i.size() == 0) {
176  continue;
177  }
178 
179  // Check exclusion string
180  bool isExclusion = i[0] == '-' || i[0] == '^';
181  // Update string
182  std::string pattern = isExclusion ? i.substr(1) : i;
183 
184  // Determine type of matching
185  size_t pos = pattern.find(":");
186  if (pos != std::string::npos) {
187  // Pattern includes separator. Just use second half
188  pattern = pattern.substr(pos + 1);
189  }
190 
191  // Match with wildcards
192  if (fnmatch(pattern.c_str(), attribute.c_str(), FNM_NOESCAPE) == 0) {
193  if (isExclusion) {
194  foundExclusion = true;
195  } else {
196  foundMatch = true;
197  }
198  }
199 
200  }
201 
202  return foundMatch && !foundExclusion;
203 }
204 
205 //------------------------------------------------------------------------------
206 
207 bool
208 match(const std::string &attribute, const std::string &patterns,
209  const MatchFlags flags)
210 {
211  return match(attribute, split(patterns), flags);
212 }
213 
214 //------------------------------------------------------------------------------
215 
216 bool
217 match(const FieldRes *f, const std::vector<std::string> &patterns,
218  const MatchFlags flags)
219 {
220  return match(f->name, f->attribute, patterns, flags);
221 }
222 
223 //------------------------------------------------------------------------------
224 
225 bool
226 match(const FieldRes *f, const std::string &patterns,
227  const MatchFlags flags)
228 {
229  return match(f->name, f->attribute, split(patterns), flags);
230 }
231 
232 //----------------------------------------------------------------------------//
233 
235 
236 //----------------------------------------------------------------------------//
FieldBase::name
std::string name
Optional name of the field.
Definition: Field.h:171
split
FIELD3D_NAMESPACE_OPEN std::vector< std::string > split(const std::string &s)
Splits a string into a vector of strings, using ',' as the separator.
Definition: PatternMatch.cpp:75
FieldRes
Definition: Field.h:207
PatternMatch.h
Contains functions for pattern matching field name/attributes.
FieldBase::attribute
std::string attribute
Optional name of the attribute the field represents.
Definition: Field.h:173
MatchFlags
MatchFlags
Definition: PatternMatch.h:64
FIELD3D_NAMESPACE_SOURCE_CLOSE
#define FIELD3D_NAMESPACE_SOURCE_CLOSE
Definition: ns.h:60
MatchEmptyPattern
Definition: PatternMatch.h:66
FIELD3D_NAMESPACE_OPEN
Definition: FieldMapping.cpp:74
match
bool match(const std::string &name, const std::string &attribute, const std::vector< std::string > &patterns, const MatchFlags flags)
Matches a <name>:<attribute> string against a set of patterns.
Definition: PatternMatch.cpp:102