All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
shz.core.PathMatcher Maven / Gradle / Ivy
package shz.core;
public final class PathMatcher {
// 匹配的path为以/分割的多级路径
// *匹配一个任意字符
// **匹配任意个任意字符
// /*/匹配一个目录
// /**/匹配一个或多个目录
private final char[] pattern;
private final int length;
private final int lastSp;
private final int spLen;
private final int[][] sps;
public PathMatcher(char[] pattern) {
this.pattern = pattern;
length = this.pattern.length;
int pl = lastSp(this.pattern);
lastSp = pl == -1 ? 0 : pl + 1;
spLen = spLen(this.pattern);
sps = sps(this.pattern, spLen);
}
private int lastSp(char[] array) {
for (int i = array.length - 1; i >= 0; --i) if (array[i] == '/') return i;
return -1;
}
private int spLen(char[] array) {
int len = 1;
int idx = 0;
while ((idx = nextSp(array, idx)) != -1) ++len;
return len;
}
private int nextSp(char[] array, int idx) {
for (int i = idx + 1; i < array.length; ++i) if (array[i] == '/') return i;
return -1;
}
private int[][] sps(char[] array, int len) {
int[][] sps = new int[len][];
for (int i = 0; i < len; ++i) sps[i] = new int[2];
sps[0][0] = array[0] == '/' ? 1 : 0;
sps[0][1] = nextSp(array, sps[0][0]);
if (sps[0][1] == -1) sps[0][1] = array.length;
else if (len > 1) {
for (int i = 1; i < len; ++i) {
sps[i][0] = sps[i - 1][1] + 1;
sps[i][1] = nextSp(array, sps[i][0]);
}
if (sps[len - 1][1] == -1) sps[len - 1][1] = array.length;
}
return sps;
}
public PathMatcher(String pattern) {
this(format(pattern));
}
public static char[] format(String pattern) {
int len = pattern.length();
StringBuilder sb = new StringBuilder(len);
char prev1 = ' ', prev2 = ' ', prev3 = ' ', prev4 = ' ', prev5;
int mark = 0;
char c;
for (int i = 0; i < len; ++i) {
c = pattern.charAt(i);
if (c == '/' || c == '\\') {
if (prev1 == '/') continue;
c = '/';
} else if (c == '*' && prev1 == '*' && prev2 == '*') continue;
prev5 = prev4;
prev4 = prev3;
prev3 = prev2;
prev2 = prev1;
prev1 = c;
if (mark == 0) {
if (prev1 == '*' && prev2 == '/' && prev3 == '*' && prev4 == '*' && (prev5 == '/' || prev5 == ' '))
mark = 1;
else sb.append(prev1);
} else if (mark == 1) {
if (prev1 == '*') mark = 2;
else {
sb.append(prev2).append(prev1);
mark = 0;
}
} else {
if (prev1 != '/') sb.append(prev3).append(prev2).append(prev1);
mark = 0;
}
}
char[] chars = new char[sb.length()];
sb.getChars(0, chars.length, chars, 0);
return chars;
}
public boolean isMatch(char[] path) {
int checkTail = checkTail(path);
if (checkTail == N) return false;
if (spLen == 1) return checkTail == S || spLen(path) == 1;
int checkHead = checkHead(path);
if (checkHead == N) return false;
if (spLen == 2) return checkTail == S || checkHead == S || spLen(path) == 2;
int pSpLen = spLen(path);
int[][] pSps = sps(path, pSpLen);
int[][] dp = new int[pSpLen][spLen];
dp[0][0] = checkHead;
dp[0][0] |= OK;
for (int i = 1; i < pSpLen; ++i) {
dp[i][0] = match(path, pSps[i][0], pSps[i][1], pattern, sps[0][0], sps[0][1]);
if (dp[i][0] == N) break;
dp[i][0] |= OK;
}
for (int j = 1; j < spLen; ++j) {
dp[0][j] = match(path, pSps[0][0], pSps[0][1], pattern, sps[j][0], sps[j][1]);
if (dp[0][j] == N) break;
dp[0][j] |= OK;
}
for (int i = 1; i < pSpLen; ++i) {
for (int j = 1; j < spLen; ++j) {
dp[i][j] = match(path, pSps[i][0], pSps[i][1], pattern, sps[j][0], sps[j][1]);
if (dp[i][j] != N) {
dp[i][j] |= dp[i - 1][j - 1];
if ((dp[i][j] & S) != 0 || (dp[i][j - 1] & S) != 0) {
dp[i][j] |= dp[i][j - 1];
dp[i][j] |= dp[i - 1][j];
}
}
}
}
return (dp[pSpLen - 1][spLen - 1] & OK) != 0;
}
private int checkTail(char[] path) {
return length < 2 ? N : match(path, lastSp(path) + 1, path.length, pattern, lastSp, length);
}
private int checkHead(char[] path) {
int[][] pSps = sps(path, 1);
return match(path, pSps[0][0], pSps[0][1], pattern, sps[0][0], sps[0][1]);
}
private static final int N = 1;
private static final int M = 1 << 1;
private static final int S = 1 << 2;
private static final int OK = 1 << 3;
private static int match(char[] path, int FL, int FR, char[] pattern, int PL, int PR) {
if (path[FR - 1] != pattern[PR - 1] && pattern[PR - 1] != '*') return N;
if (path[FL] != pattern[PL] && pattern[PL] != '*') return N;
if (PR - PL == 1) return pattern[PL] == '*' ? M : FR - FL > 1 || path[FL] != pattern[PL] ? N : M;
if (PR - PL == 2) {
if (pattern[PL] == '*' && pattern[PL + 1] == '*') return S;
if (FR - FL != 2) return N;
if (pattern[PL + 1] == '*') return path[FL] == pattern[PL] ? M : N;
if (pattern[PL] == '*') return path[FL + 1] == pattern[PL + 1] ? M : N;
return path[FL] == pattern[PL] && path[FL + 1] == pattern[PL + 1] ? M : N;
}
boolean[][] dp = new boolean[FR - FL][PR - PL];
dp[0][0] = true;
for (int i = 1; i < FR - FL; ++i) {
for (int j = 1; j < PR - PL; ++j) {
if (path[i + FL] == pattern[j + PL] || pattern[j + PL] == '*') {
dp[i][j] |= dp[i - 1][j - 1];
if (pattern[j - 1 + PL] == '*' && (pattern[j + PL] == '*' || (j >= 2 && pattern[j - 2 + PL] == '*'))) {
dp[i][j] |= dp[i][j - 1];
dp[i][j] |= dp[i - 1][j];
}
}
}
}
return dp[FR - FL - 1][PR - PL - 1] ? M : N;
}
public boolean isMatch(String path) {
return isMatch(path.toCharArray());
}
public char[] getPattern() {
return pattern;
}
}