in src/main/java/org/apache/sling/commons/jcr/file/internal/PathUtil.java [44:113]
static String normalize(@NotNull String path) {
// don't care for empty paths
if (path.length() == 0) {
return path;
}
// prepare the path buffer with trailing slash (simplifies impl)
int absOffset = (path.charAt(0) == '/') ? 0 : 1;
char[] buf = new char[path.length() + 1 + absOffset];
if (absOffset == 1) {
buf[0] = '/';
}
path.getChars(0, path.length(), buf, absOffset);
buf[buf.length - 1] = '/';
int lastSlash = 0; // last slash in path
int numDots = 0; // number of consecutive dots after last slash
int bufPos = 0;
for (int bufIdx = lastSlash; bufIdx < buf.length; bufIdx++) {
char c = buf[bufIdx];
if (c == '/') {
if (numDots == 2) {
if (bufPos == 0) {
return null;
}
do {
bufPos--;
} while (bufPos > 0 && buf[bufPos] != '/');
}
lastSlash = bufIdx;
numDots = 0;
} else if (c == '.' && useDot(buf, bufIdx) && numDots < 2) {
numDots++;
} else {
// find the next slash
int nextSlash = bufIdx + 1;
while (nextSlash < buf.length && buf[nextSlash] != '/') {
nextSlash++;
}
// append up to the next slash (or end of path)
if (bufPos < lastSlash) {
int segLen = nextSlash - bufIdx + 1;
System.arraycopy(buf, lastSlash, buf, bufPos, segLen);
bufPos += segLen;
} else {
bufPos = nextSlash;
}
numDots = 0;
lastSlash = nextSlash;
bufIdx = nextSlash;
}
}
String resolved;
if (bufPos == 0 && numDots == 0) {
resolved = (absOffset == 0) ? "/" : "";
} else if ((bufPos - absOffset) == path.length()) {
resolved = path;
} else {
resolved = new String(buf, absOffset, bufPos - absOffset);
}
return resolved;
}