1 /*
2  * Hunt - A refined core library for D programming language.
3  *
4  * Copyright (C) 2018-2019 HuntLabs
5  *
6  * Website: https://www.huntlabs.net/
7  *
8  * Licensed under the Apache-2.0 License.
9  *
10  */
11 
12 module hunt.text.PatternMatchUtils;
13 
14 import hunt.text.Common;
15 
16 import std.range.primitives;
17 import std.string;
18 
19 /**
20  * Utility methods for simple pattern matching, in particular for
21  * Spring's typical "xxx*", "*xxx" and "*xxx*" pattern styles.
22  *
23  * @author Juergen Hoeller
24  */
25 abstract class PatternMatchUtils {
26 
27 	/**
28 	 * Match a string against the given pattern, supporting the following simple
29 	 * pattern styles: "xxx*", "*xxx", "*xxx*" and "xxx*yyy" matches (with an
30 	 * arbitrary number of pattern parts), as well as direct equality.
31 	 * @param pattern the pattern to match against
32 	 * @param str the string to match
33 	 * @return whether the string matches the given pattern
34 	 */
35 	static bool simpleMatch(string pattern, string str) {
36 		if (pattern.empty || str.empty) {
37 			return false;
38 		}
39 		ptrdiff_t firstIndex = pattern.indexOf('*');
40 		if (firstIndex == -1) {
41 			return pattern == str;
42 		}
43 		if (firstIndex == 0) {
44 			if (pattern.length == 1) {
45 				return true;
46 			}
47 			ptrdiff_t nextIndex = pattern.indexOf('*', firstIndex + 1);
48 			if (nextIndex == -1) {
49 				return str.endsWith(pattern.substring(1));
50 			}
51 			string part = pattern.substring(1, nextIndex);
52 			if ("" == part) {
53 				return simpleMatch(pattern.substring(nextIndex), str);
54 			}
55 			ptrdiff_t partIndex = str.indexOf(part);
56 			while (partIndex != -1) {
57 				if (simpleMatch(pattern.substring(nextIndex), str.substring(partIndex + part.length))) {
58 					return true;
59 				}
60 				partIndex = str.indexOf(part, partIndex + 1);
61 			}
62 			return false;
63 		}
64 		return (str.length >= firstIndex &&
65 				pattern.substring(0, firstIndex).equals(str.substring(0, firstIndex)) &&
66 				simpleMatch(pattern.substring(firstIndex), str.substring(firstIndex)));
67 	}
68 
69 	/**
70 	 * Match a string against the given patterns, supporting the following simple
71 	 * pattern styles: "xxx*", "*xxx", "*xxx*" and "xxx*yyy" matches (with an
72 	 * arbitrary number of pattern parts), as well as direct equality.
73 	 * @param patterns the patterns to match against
74 	 * @param str the string to match
75 	 * @return whether the string matches any of the given patterns
76 	 */
77 	static bool simpleMatch(string[] patterns, string str) {
78 		if (patterns !is null) {
79 			foreach (string pattern ; patterns) {
80 				if (simpleMatch(pattern, str)) {
81 					return true;
82 				}
83 			}
84 		}
85 		return false;
86 	}
87 
88 }