/*
This file is part of jpcsp.
Jpcsp is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Jpcsp is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Jpcsp. If not, see <http://www.gnu.org/licenses/>.
*/
package jpcsp.HLE.VFS;
import static jpcsp.HLE.VFS.xmb.XmbVirtualFileSystem.PSP_GAME;
import java.util.HashMap;
import jpcsp.HLE.VFS.local.LocalVirtualFileSystem;
import jpcsp.HLE.VFS.xmb.XmbVirtualFileSystem;
public class VirtualFileSystemManager {
protected HashMap<String, IVirtualFileSystem> virtualFileSystems = new HashMap<String, IVirtualFileSystem>();
private IVirtualFileSystem xmbVfs;
public void register(String name, IVirtualFileSystem vfs) {
name = name.toLowerCase();
virtualFileSystems.put(name, vfs);
}
public void unregister(String name) {
name = name.toLowerCase();
virtualFileSystems.remove(name);
}
public IVirtualFileSystem getVirtualFileSystem(String absoluteFileName, StringBuilder localFileName) {
int colon = absoluteFileName.indexOf(':');
if (colon < 0) {
return null;
}
String name = absoluteFileName.substring(0, colon);
name = name.toLowerCase();
if (localFileName != null) {
localFileName.setLength(0);
localFileName.append(absoluteFileName.substring(colon + 1));
normalizeLocalFileName(localFileName);
if ("ms0".equals(name) && localFileName.toString().startsWith(PSP_GAME)) {
if (xmbVfs == null) {
xmbVfs = new XmbVirtualFileSystem(new LocalVirtualFileSystem("ms0/", true));
}
return xmbVfs;
}
}
return virtualFileSystems.get(name);
}
/**
* Normalize the given local file name:
* - resolve ".." and "." special notation
* - remove leading and trailing "/"
*
* @param localFileName the local file name to be normalized
*/
private void normalizeLocalFileName(StringBuilder localFileName) {
// Remove "/../" in the local file name
// E.g.:
// /PSP_GAME/USRDIR/A/../B
// is transformed into
// /PSP_GAME/USRDIR/B
while (true) {
int dotDotIndex = localFileName.indexOf("/../");
if (dotDotIndex < 0) {
break;
}
int parentIndex = localFileName.lastIndexOf("/", dotDotIndex - 1);
if (parentIndex < 0) {
break;
}
localFileName.delete(parentIndex, dotDotIndex + 3);
}
// Remove "/.." at the end of the local file name
// E.g.:
// PSP_GAME/USRDIR/A/..
// is transformed into
// PSP_GAME/USRDIR
if (localFileName.length() >= 3 && localFileName.lastIndexOf("/..") == localFileName.length() - 3) {
if (localFileName.length() <= 3) {
localFileName.setLength(0);
} else {
int parentIndex = localFileName.lastIndexOf("/", localFileName.length() - 4);
if (parentIndex < 0) {
localFileName.setLength(0);
} else {
localFileName.setLength(parentIndex);
}
}
}
// Remove "/./" in the local file name
// E.g.:
// PSP_GAME/USRDIR/A/./B
// is transformed into
// PSP_GAME/USRDIR/A/B
while (true) {
int dotIndex = localFileName.indexOf("/./");
if (dotIndex < 0) {
break;
}
localFileName.delete(dotIndex, dotIndex + 2);
}
// Remove "/." at the end of the local file name
// E.g.:
// PSP_GAME/USRDIR/A/.
// is transformed into
// PSP_GAME/USRDIR/A
if (localFileName.length() >= 2 && localFileName.lastIndexOf("/.") == localFileName.length() - 2) {
localFileName.setLength(localFileName.length() - 2);
}
// Delete any leading "/"
if (localFileName.length() > 0 && localFileName.charAt(0) == '/') {
localFileName.deleteCharAt(0);
}
// Delete any trailing "/"
if (localFileName.length() > 0 && localFileName.charAt(localFileName.length() - 1) == '/') {
localFileName.setLength(localFileName.length() - 1);
}
}
public static String getFileNameLastPart(String fileName) {
if (fileName != null) {
int lastSepIndex = fileName.lastIndexOf('/');
if (lastSepIndex >= 0) {
fileName = fileName.substring(lastSepIndex + 1);
}
}
return fileName;
}
}