/*
* Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* bstefanescu
*/
package org.eclipse.ecr.web.jaxrs.servlet.mapping;
/**
* @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
*
*/
public class PathParser {
protected String[] array;
protected int count;
protected char[] buf;
protected int bufCount;
public PathParser() {
reset();
}
public void reset() {
array = new String[16];
buf = new char[16];
count = 0;
bufCount = 0;
}
public Path parse(String path) {
return parse(path, -1);
}
public Path parse(String path, int userBits) {
char[] chars = path.toCharArray();
if (chars.length == 0) {
return Path.EMPTY;
}
if (chars.length == 1 && chars[0] == '/') {
return Path.ROOT;
}
int i = 0;
int len = chars.length;
int bits = 0;
if (chars[chars.length-1] == '/') {
bits |= Path.HAS_TRAILING_SLASH;
len--;
}
if (chars[0] == '/') {
bits |= Path.HAS_LEADING_SLASH;
i++;
}
for (; i<len; i++) {
char c = chars[i];
if (c == '/') {
if (hasSegment()) {
addSegment(currentSegment());
resetBuf();
} // else -> duplicate / - it will be ignored
} else {
append(c);
}
}
if (hasSegment()) {
addSegment(currentSegment());
}
return new Path(getSegments(), userBits == -1 ? bits : userBits);
}
public void back() {
if (count == 0) {
add("..");
} else {
count--;
}
}
public void addSegment(String segment) {
if ("..".equals(segment)) {
back();
} else if (!".".equals(segment)) {
add(segment);
}
}
public String[] getSegments() {
String[] result = new String[count];
System.arraycopy(array, 0, result, 0, count);
return result;
}
private final void add(String segment) {
if (count + 1 == array.length) {
String[] result = new String[count+16];
System.arraycopy(array, 0, result, 0, count);
array = result;
}
array[count++] = segment;
}
private final void append(char c) {
if (bufCount + 1 == buf.length) {
char[] result = new char[bufCount+16];
System.arraycopy(buf, 0, result, 0, bufCount);
buf = result;
}
buf[bufCount++] = c;
}
private final String currentSegment() {
return new String(buf, 0, bufCount);
}
private final boolean hasSegment() {
return bufCount > 0;
}
private final void resetBuf() {
bufCount = 0;
}
}