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  * @since 2.0
25  */
26 abstract class PatternMatchUtils {
27 
28 	/**
29 	 * Match a string against the given pattern, supporting the following simple
30 	 * pattern styles: "xxx*", "*xxx", "*xxx*" and "xxx*yyy" matches (with an
31 	 * arbitrary number of pattern parts), as well as direct equality.
32 	 * @param pattern the pattern to match against
33 	 * @param str the string to match
34 	 * @return whether the string matches the given pattern
35 	 */
36 	static bool simpleMatch(string pattern, string str) {
37 		if (pattern.empty || str.empty) {
38 			return false;
39 		}
40 		ptrdiff_t firstIndex = pattern.indexOf('*');
41 		if (firstIndex == -1) {
42 			return pattern == str;
43 		}
44 		if (firstIndex == 0) {
45 			if (pattern.length == 1) {
46 				return true;
47 			}
48 			ptrdiff_t nextIndex = pattern.indexOf('*', firstIndex + 1);
49 			if (nextIndex == -1) {
50 				return str.endsWith(pattern.substring(1));
51 			}
52 			string part = pattern.substring(1, nextIndex);
53 			if ("" == part) {
54 				return simpleMatch(pattern.substring(nextIndex), str);
55 			}
56 			ptrdiff_t partIndex = str.indexOf(part);
57 			while (partIndex != -1) {
58 				if (simpleMatch(pattern.substring(nextIndex), str.substring(partIndex + part.length))) {
59 					return true;
60 				}
61 				partIndex = str.indexOf(part, partIndex + 1);
62 			}
63 			return false;
64 		}
65 		return (str.length >= firstIndex &&
66 				pattern.substring(0, firstIndex).equals(str.substring(0, firstIndex)) &&
67 				simpleMatch(pattern.substring(firstIndex), str.substring(firstIndex)));
68 	}
69 
70 	/**
71 	 * Match a string against the given patterns, supporting the following simple
72 	 * pattern styles: "xxx*", "*xxx", "*xxx*" and "xxx*yyy" matches (with an
73 	 * arbitrary number of pattern parts), as well as direct equality.
74 	 * @param patterns the patterns to match against
75 	 * @param str the string to match
76 	 * @return whether the string matches any of the given patterns
77 	 */
78 	static bool simpleMatch(string[] patterns, string str) {
79 		if (patterns !is null) {
80 			foreach (string pattern ; patterns) {
81 				if (simpleMatch(pattern, str)) {
82 					return true;
83 				}
84 			}
85 		}
86 		return false;
87 	}
88 
89 }