|
Das Backslash-Zeichen wird im Define
#define SLASH '\\'
vorgegeben, wobei unter DOS „\\“ und unter UNIX „/“ zum Einsatz kommt. Die Grundlogik der Funktion GetRelativeFilename() besteht darin, die Anzahl der übereinstimmenden Verzeichnisse von Basisverzeichnis und absolutem Dateinamen zu ermitteln und für die gefundene Anzahl die entsprechende Anzahl von Verweisen auf das Elternverzeichnis „..\“ einzusetzen.
Dazu durchläuft die Funktion die beiden Strings, bis ein Ergebnis gefunden ist, maximal jedoch nur über die Länge des kürzeren der beiden Strings, deren Längen gleich zu Beginn der Funktion ermittelt und in cdLen bzw. afLen abgelegt werden.
char* GetRelativeFilename(char *currentDirectory,
char *absoluteFilename)
{
int afMarker = 0; // Index in absoluten Dateinamen
int rfMarker = 0; // Index in relativen Dateinamen
int cdLen = 0; // Länge Basisverzeichnis
int afLen = 0; // Länger absoluter Dateiname
int i = 0;
int levels = 0; // Unterschiedsebenen
static char relativeFilename[MAX_FILENAME_LEN+1];
cdLen = strlen(currentDirectory);
afLen = strlen(absoluteFilename);
Nachdem die Längen bekannt sind, erfolgt eine Überprüfung, um sicherzustellen, daß die Strings nicht länger als erlaubt und nicht kürzer als der kürzest mögliche Name sind.
if (cdLen > MAX_FILENAME_LEN || cdLen < ABSOLUTE_NAME_START+1 ||
afLen > MAX_FILENAME_LEN || afLen < ABSOLUTE_NAME_START+1)
return NULL;
Ein Sonderfall liegt vor, wenn Basisverzeichnis und absoluter Dateiname unterschiedliche Laufwerke beinhalten. In diesem Fall entspricht der relative Dateiname dem absoluten.
if(currentDirectory[0] != absoluteFilename[0])
{
strcpy(relativeFilename, absoluteFilename);
return relativeFilename;
}
Liegen Basisverzeichnis und absoluter Dateiname auf dem gleichen Laufwerk, ist herauszufinden, wieviel des Basisverzeichnisses im absoluten Dateinamen enthalten ist.
i = ABSOLUTE_NAME_START;
while(i < afLen &&
i < cdLen &&
currentDirectory[i] == absoluteFilename[i])
{
i++;
}
Ist das gesamte Basisverzeichnis im absoluten Dateinamen enthalten, muß nur der verbleibende Rest abgeschnitten werden, um den relativen Dateinamen zu erhalten. Es ist sicherzustellen, daß der relative Dateiname keinen abschließenden Backslash besitzt, da dies nur für Verzeichnisse erlaubt ist.
if(i == cdLen && (absoluteFilename[i] == SLASH ||
absoluteFilename[i-1] == SLASH))
{
if (absoluteFilename[i] == SLASH)
i++;
strcpy(relativeFilename, &absoluteFilename[i]);
return relativeFilename;
}
Liegt die Datei nicht in einem Unterverzeichnis des Basisverzeichnisses, muß ausgehend vom vollständigen Basisverzeichnis in Richtung Wurzel zurückgeschritten werden, indem eine entsprechende Anzahl von „..\“ eingefügt wird. Dazu gilt es zunächst herauszufinden, um wie viele Ebenen der Dateiname tiefer liegt als das tiefste gemeinsame Verzeichnis.
|