Skip to content

Commit 96823d8

Browse files
committed
Partially reverted 17b6225 back to a98b66d (with some variations)
1 parent 17b6225 commit 96823d8

File tree

3 files changed

+237
-280
lines changed

3 files changed

+237
-280
lines changed

src/Wildcard.cpp

Lines changed: 153 additions & 182 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,24 @@
2929

3030
namespace shellanything
3131
{
32-
typedef std::vector<WildcardResult> WildcardResultList;
32+
static const size_t INVALID_WILDCARD_POSITION = (size_t)-1;
33+
34+
size_t GetNextWildcardPosition(const size_t * wildcard_positions, size_t num_wildcards, size_t current)
35+
{
36+
for(size_t i=0; i<num_wildcards; i++)
37+
{
38+
const size_t & pos = wildcard_positions[i];
39+
if (pos == current)
40+
{
41+
if (i+1 < num_wildcards)
42+
{
43+
return wildcard_positions[i+1];
44+
}
45+
return INVALID_WILDCARD_POSITION; //requested wildcard is the last one
46+
}
47+
}
48+
return INVALID_WILDCARD_POSITION; //wildcard position not found
49+
}
3350

3451
bool IsWildcard(char c)
3552
{
@@ -136,224 +153,178 @@ namespace shellanything
136153
return true;
137154
}
138155

139-
bool WildcardSolve(const char * pattern, const char * value, WildcardResultList * presults)
156+
bool WildcardSolve( const char * pattern,
157+
const char * value,
158+
const size_t * wildcard_positions,
159+
size_t num_wildcards,
160+
const int iIndexWild,
161+
const int iIndexValue,
162+
WildcardList & matches)
140163
{
141-
size_t pattern_length = strlen(pattern);
142-
size_t value_length = strlen(value);
143-
144-
// If the pattern is empty, the value must also be empty to match.
145-
if (pattern_length == 0)
164+
int indexWild = iIndexWild;
165+
int indexValue = iIndexValue;
166+
int wildLen = (int)std::string(pattern).size();
167+
int valueLen = (int)std::string(value).size();
168+
169+
//while wildcard and value not fully solved
170+
while (indexWild < wildLen || indexValue < valueLen)
146171
{
147-
// If not, then there is not match.
148-
if (value_length == 0)
172+
const char & cWild = pattern[indexWild];
173+
const char & cValue = value[indexValue];
174+
if ( !IsWildcard(cWild) )
149175
{
150-
//if (presults)
151-
//{
152-
// WildcardResult r = {0};
153-
// r.valid = true;
154-
// r.pattern_offset = 0;
155-
// r.value = value;
156-
// r.value_length = 0;
157-
// presults->push_back(r);
158-
//}
159-
return true;
160-
}
161-
return false;
162-
}
176+
if (cWild != cValue)
177+
return false; //characters don't match!
163178

164-
// If the value is empty, the pattern must be '*' (or a '*' sequence) to match
165-
if (value_length == 0)
166-
{
167-
if (!IsStarSequence(&pattern[0]))
168-
return false;
169-
170-
// We have a match.
171-
if (presults)
172-
{
173-
WildcardResult r = {0};
174-
r.valid = true;
175-
r.pattern_offset = 0;
176-
r.value = value;
177-
r.value_length = 0;
178-
presults->push_back(r);
179+
//next char
180+
indexWild++;
181+
indexValue++;
179182
}
180-
181-
return true;
182-
}
183-
184-
// At this point, both pattern and value are not empty
185-
186-
size_t value_offset = 0;
187-
for(size_t pattern_offset = 0; pattern_offset < pattern_length; pattern_offset++)
188-
{
189-
const char & pattern_char = pattern[pattern_offset];
190-
const char & value_char = value[value_offset];
191-
192-
// If we reached a '*' sequence, move forward to the last '*' character of the sequence
193-
while(pattern[pattern_offset] == '*' && (pattern_offset+1 < pattern_length) && pattern[pattern_offset+1] == '*')
183+
else
194184
{
195-
pattern_offset++;
196-
}
197-
198-
size_t remaining_pattern_length = pattern_length - pattern_offset;
199-
size_t remaining_value_length = value_length - value_offset;
185+
//cWild is wildcard
186+
if (cWild == '?')
187+
{
188+
//save wildcard resolve information
189+
WILDCARD w;
190+
w.character = cWild;
191+
w.index = indexWild;
192+
w.value = cValue;
193+
matches.push_back(w);
194+
195+
//next char
196+
indexWild++;
197+
indexValue++;
198+
}
199+
else if (cWild == '*')
200+
{
201+
//if wildcard character * is the last one
202+
if (indexWild+1 >= wildLen)
203+
{
204+
//automatically match the end of the string
200205

201-
// If we reached the end of both strings, we are done searching
202-
if (remaining_pattern_length == 0 && remaining_value_length == 0)
203-
return true;
206+
//save wildcard resolve information
207+
WILDCARD w;
208+
w.character = cWild;
209+
w.index = indexWild;
210+
w.value = &cValue;
211+
matches.push_back(w);
204212

205-
// If the pattern is '*', and the next pattern character is valid, and the value is empty, then we won't be able to match.
206-
// (because there is a next non-wildcard character in the pattern)
207-
if (pattern_char == '*' &&
208-
(pattern_offset+1 < pattern_length) && // pattern has more characters
209-
pattern[pattern_offset+1] != '\0' && // next pattern character is valid)
210-
remaining_value_length == 0) // value is empty
211-
{
212-
return false;
213-
}
213+
// If we reached a '*' sequence, move forward to the last '*' character of the sequence
214+
while(pattern[indexWild] == '*' && (indexWild+1 < wildLen) && pattern[indexWild+1] == '*')
215+
{
216+
indexWild++;
217+
}
214218

215-
if (pattern_char == '?')
216-
{
217-
// In order to match, the '?' must match the current value character
218-
if (value_char == '\0')
219-
return false; // We reached the end of the value string
219+
//next char
220+
indexWild++;
221+
indexValue += (int)w.value.size();
222+
}
223+
else
224+
{
225+
//wildcard character * is not the last one
220226

221-
// We matched this wildcard character
222-
// Save this wildcard expansion
223-
if (presults)
224-
{
225-
WildcardResult r = {0};
226-
r.valid = true;
227-
r.pattern_offset = pattern_offset;
228-
r.value = &value[value_offset];
229-
r.value_length = 1;
230-
presults->push_back(r);
231-
}
227+
//compute all possibilities that can fit in * and then use recursion to check if it can be resolved
228+
//compute the possibilities in the from the longest to the shortest ("") for optimizing the replacement string
229+
//since all wildcard caracters must be mapped, do not compute possibilities beyond the next wildcard character
232230

233-
// Advance both offsets and keep on looking
234-
value_offset++;
235-
}
236-
else if (pattern_char == value_char)
237-
{
238-
// Advance both offsets and keep on looking
239-
value_offset++;
240-
}
241-
else if (pattern_char == '*')
242-
{
243-
// Found a '*' character or sequence.
244-
// From this point, there are 2 possibilities.
231+
//compute next character
232+
const char & nextWild = (&cWild)[1];
245233

246-
WildcardResultList tmp;
247-
WildcardResultList * sub_results = NULL;
248-
if (presults)
249-
sub_results = &tmp;
234+
int nextWildcardPosition = (int)GetNextWildcardPosition(wildcard_positions, num_wildcards, indexWild);
250235

251-
// 1) The '*' replaces the next value character.
252-
bool match = WildcardSolve(&pattern[pattern_offset], &value[value_offset+1], sub_results);
253-
if (match)
254-
{
255-
// Add the sub results to our results
256-
if (presults)
257-
{
258-
for(size_t i=0; i<sub_results->size(); i++)
236+
//compute fixed characters between this wildcard and the last one (of the end of the file)
237+
//ie: fgh in abc*fgh?j or abc*fgh
238+
std::string fixedCharacters = &nextWild;
239+
if (nextWildcardPosition != -1)
259240
{
260-
WildcardResult & r = (*sub_results)[i];
261-
r.pattern_offset += pattern_offset;
262-
presults->push_back(r);
241+
//there is at least another wildcard character after this one
242+
fixedCharacters = &nextWild;
243+
size_t size = nextWildcardPosition - indexWild;
244+
fixedCharacters.resize(size);
263245
}
264-
sub_results->clear();
265-
}
266246

267-
return true;
268-
}
247+
//compute maximum length of replacementString
248+
int remainingCharactersInValue = valueLen-indexValue;
249+
int replacementStringMaxLength = remainingCharactersInValue-(int)fixedCharacters.size();
269250

270-
// 2) The '*' does not replaces the next value character.
271-
match = WildcardSolve(&pattern[pattern_offset+1], &value[value_offset], sub_results);
272-
if (match)
273-
{
274-
// Add the sub results to our results
275-
if (presults)
276-
{
277-
for(size_t i=0; i<sub_results->size(); i++)
251+
//compute all possibilities that can fit in * with a length in [0,replacementStringMaxLength]
252+
for(int length=replacementStringMaxLength; length>=0; length--)
278253
{
279-
WildcardResult & r = (*sub_results)[i];
280-
r.pattern_offset += pattern_offset+1;
281-
presults->push_back(r);
254+
//assuming replacement string is the right one
255+
256+
std::string replacementString = &cValue;
257+
replacementString.resize(length);
258+
259+
WildcardList tmpList = matches;
260+
261+
//save wildcard resolve information
262+
WILDCARD w;
263+
w.character = cWild;
264+
w.index = indexWild;
265+
w.value = replacementString;
266+
tmpList.push_back(w);
267+
268+
//next char
269+
int tmpIndexWild = indexWild+1;
270+
int tmpIndexValue = indexValue + (int)w.value.size();
271+
272+
//execute recursive call
273+
bool solved = WildcardSolve(pattern, value, wildcard_positions, num_wildcards, tmpIndexWild, tmpIndexValue, tmpList);
274+
if (solved)
275+
{
276+
//solved!
277+
//refresh matches
278+
matches = tmpList;
279+
return true;
280+
}
282281
}
283-
sub_results->clear();
284-
}
285282

286-
return true;
283+
//all possibilities were checked
284+
//unable to solve * wildcard
285+
return false;
286+
}
287287
}
288-
289-
// We recurse on all possibilities. No match found.
290-
return false;
291-
}
292-
else
293-
{
294-
// Characters from pattern and value does not match
295-
return false;
296288
}
297289
}
298290

299-
// We reached the end of the pattern, the value must be empty too to match
300-
if (value[value_offset] != '\0')
301-
return false;
302-
303-
//// The remaining of the value is the expansion of the last wildcard character
304-
//if (presults)
305-
//{
306-
// WildcardResult r = {0};
307-
// r.valid = true;
308-
// r.pattern_offset = 0;
309-
// r.value = value;
310-
// r.value_length = 0;
311-
// presults->push_back(r);
312-
//}
313-
314-
return true;
291+
if (indexWild == wildLen && indexValue == valueLen)
292+
return true; //solved
293+
if ((indexWild == wildLen && indexValue < valueLen) ||
294+
(indexWild == wildLen && indexValue < valueLen) )
295+
return false; //reached the end of wildcard or the end of value
296+
return false; //???
315297
}
316298

317-
bool WildcardSolve(const char * pattern, const char * value, WildcardResult * results_array, size_t results_size)
299+
bool WildcardSolve(const char * pattern, const char * value, WildcardList & matches)
318300
{
319-
size_t results_array_count = results_size / sizeof(WildcardResult);
320-
bool has_array = (results_array != NULL && results_array_count > 0);
321-
if (has_array)
322-
memset(results_array, 0, results_size);
323-
324301
if (pattern == NULL || value == NULL)
325302
return false;
326303

304+
matches.clear();
305+
327306
// Force the pattern to its simplest form
328307
std::string simplified_pattern = pattern;
329308
WildcardSimplify(simplified_pattern);
330309

331-
// Create a results list if required
332-
WildcardResultList results;
333-
WildcardResultList * presults = NULL;
334-
if (has_array)
335-
presults = &results;
310+
// Find all wildcard character positions
311+
size_t num_wildcards = FindWildcardCharacters(simplified_pattern.c_str(), NULL, 0);
312+
313+
// If no wildcard character found, the strings must be equal
314+
if (num_wildcards == 0)
315+
return (std::string(pattern) == std::string(value));
336316

337-
// Search for a possible match
338-
bool match = WildcardSolve(simplified_pattern.c_str(), value, presults);
339-
if (!match)
340-
return false;
317+
// Allocate memory for all wildcard positions
318+
size_t * wildcard_positions = new size_t[num_wildcards];
319+
FindWildcardCharacters(simplified_pattern.c_str(), wildcard_positions, num_wildcards);
341320

342-
if (has_array)
343-
{
344-
// The pattern and value matches
345-
// Copy the results list into results_array
346-
#define MIN(a,b) ((a) < (b) ? (a) : (b))
347-
size_t count = MIN(results.size(), results_array_count);
348-
#undef MIN
349-
for(size_t i=0; i<count; i++)
350-
{
351-
const WildcardResult & result = results[i];
352-
results_array[i] = result;
353-
}
354-
}
321+
//solve wildcards
322+
bool solved = WildcardSolve(simplified_pattern.c_str(), value, wildcard_positions, num_wildcards, 0, 0, matches);
355323

356-
return true;
324+
delete[] wildcard_positions;
325+
wildcard_positions = NULL;
326+
327+
return solved;
357328
}
358329

359330
} //namespace shellanything

0 commit comments

Comments
 (0)