moved files around
This commit is contained in:
305
Extras/FCollada/FUtils/FUFileManager.cpp
Normal file
305
Extras/FCollada/FUtils/FUFileManager.cpp
Normal file
@@ -0,0 +1,305 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
/*
|
||||
Based on the FS Import classes:
|
||||
Copyright (C) 2005-2006 Feeling Software Inc
|
||||
Copyright (C) 2005-2006 Autodesk Media Entertainment
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "FUtils/FUFile.h"
|
||||
#include "FUtils/FUFileManager.h"
|
||||
#include "FUtils/FUStringConversion.h"
|
||||
|
||||
#if defined(WIN32)
|
||||
#include <direct.h>
|
||||
#endif
|
||||
|
||||
FUFileManager::FUFileManager()
|
||||
{
|
||||
// Push on the stack the original root path
|
||||
char fullPath[MAX_PATH];
|
||||
getcwd(fullPath, MAX_PATH);
|
||||
pathStack.push_back(TO_FSTRING(fullPath));
|
||||
}
|
||||
|
||||
FUFileManager::~FUFileManager()
|
||||
{
|
||||
}
|
||||
|
||||
// Set a new root path
|
||||
void FUFileManager::PushRootPath(const fstring& path)
|
||||
{
|
||||
// Ensure that the new root path is an absolute root path.
|
||||
fstring absolutePath = MakeFilePathAbsolute(path);
|
||||
pathStack.push_back(absolutePath);
|
||||
fchdir(path.c_str());
|
||||
}
|
||||
|
||||
// Go back to the previous root path
|
||||
void FUFileManager::PopRootPath()
|
||||
{
|
||||
if (pathStack.size() > 1)
|
||||
{
|
||||
pathStack.pop_back();
|
||||
fchdir(pathStack.back().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// Set the current path root, using a known filename
|
||||
void FUFileManager::PushRootFile(const fstring& filename)
|
||||
{
|
||||
// Strip the filename of the actual file's name
|
||||
fstring path = StripFileFromPath(filename);
|
||||
PushRootPath(path);
|
||||
}
|
||||
|
||||
void FUFileManager::PopRootFile()
|
||||
{
|
||||
PopRootPath();
|
||||
}
|
||||
|
||||
// Open a file to read
|
||||
FUFile* FUFileManager::OpenFile(const fstring& filename, bool write)
|
||||
{
|
||||
fstring absoluteFilename = MakeFilePathAbsolute(filename);
|
||||
string dumpFilename = FUStringConversion::ToString(absoluteFilename);
|
||||
return new FUFile(dumpFilename.c_str(), write ? FUFile::WRITE : FUFile::READ);
|
||||
}
|
||||
|
||||
// Massage a given filename to be absolute
|
||||
fstring FUFileManager::GetFilePath(const fstring& fileURL)
|
||||
{
|
||||
// Strip any prefix
|
||||
fstring filename = fileURL;
|
||||
std::replace(filename.begin(), filename.end(), '\\', '/');
|
||||
if (filename.size() > 7 && filename.substr(0, 7) == FC("file://"))
|
||||
{
|
||||
filename = filename.c_str() + 7;
|
||||
|
||||
if (filename.size() > 3 && filename[0] == '/' && (filename[2] == ':' || filename[2] == '|'))
|
||||
{
|
||||
filename = filename.c_str() + 1;
|
||||
}
|
||||
|
||||
if (filename[1] == '|') filename[1] = ':';
|
||||
}
|
||||
|
||||
// Replace any '%' character string into the wanted characters: %20 is common.
|
||||
for (size_t pos = filename.find('%'); pos != fstring::npos; pos = filename.find('%'))
|
||||
{
|
||||
const fchar* pc = filename.c_str() + pos + 1; // +1 to skip/erase the '%' character
|
||||
uint32 value = FUStringConversion::HexToUInt32(&pc, 2);
|
||||
size_t count = (pc - filename.c_str()) - pos;
|
||||
filename.erase(pos, count);
|
||||
filename.insert(pos, 1, (fchar) value);
|
||||
}
|
||||
|
||||
return MakeFilePathAbsolute(filename);
|
||||
}
|
||||
|
||||
// Transform a file path into a file URL
|
||||
fstring FUFileManager::GetFileURL(const fstring& filepath, bool relative)
|
||||
{
|
||||
fstring url;
|
||||
if (relative)
|
||||
{
|
||||
url = MakeFilePathRelative(filepath);
|
||||
if (!url.empty() && url[0] != '.')
|
||||
{
|
||||
// Unable to make the path relative, so return an absolute path
|
||||
relative = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!relative)
|
||||
{
|
||||
// Transform into an absolute file path
|
||||
fstring url = MakeFilePathAbsolute(filepath);
|
||||
std::replace(url.begin(), url.end(), ':', '|');
|
||||
std::replace(url.begin(), url.end(), '\\', '/');
|
||||
url = fstring(FC("file://")) + url;
|
||||
}
|
||||
|
||||
// Remove any invalid character(s) using the %X guideline
|
||||
/*for (size_t p = 0; p < url.size(); ++p)
|
||||
{
|
||||
fchar c = url[p];
|
||||
if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') ||
|
||||
c == '.' || c == '|' || c == '/' || c == '-' || c == '_')
|
||||
{
|
||||
// Valid characters
|
||||
}
|
||||
else
|
||||
{
|
||||
url.erase(p, 1);
|
||||
globalBuilder.set('%'); <---- NEED TO BE IN HEX
|
||||
globalBuilder.append(c);
|
||||
url.append(globalBuilder.ToCharPtr());
|
||||
}
|
||||
}*/
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
// Strip a full filename of its filename, returning the path
|
||||
fstring FUFileManager::StripFileFromPath(const fstring& filename)
|
||||
{
|
||||
fchar fullPath[MAX_PATH + 1];
|
||||
fstrncpy(fullPath, filename.c_str(), MAX_PATH);
|
||||
fullPath[MAX_PATH] = 0;
|
||||
fchar* lastSlash = fstrrchr(fullPath, FC('/'));
|
||||
fchar* lastBackslash = fstrrchr(fullPath, FC('\\'));
|
||||
lastSlash = max(lastSlash, lastBackslash);
|
||||
if (lastSlash != NULL) *lastSlash = 0;
|
||||
return fstring(fullPath);
|
||||
}
|
||||
|
||||
// Extract the file extension out of a filename
|
||||
fstring FUFileManager::GetFileExtension(const fstring& _filename)
|
||||
{
|
||||
fchar filename[MAX_PATH];
|
||||
fstrncpy(filename, _filename.c_str(), MAX_PATH);
|
||||
filename[MAX_PATH - 1] = 0;
|
||||
|
||||
fchar* lastPeriod = fstrrchr(filename, '.');
|
||||
if (lastPeriod == NULL) return fstring();
|
||||
|
||||
fchar* lastSlash = fstrrchr(filename, '/');
|
||||
fchar* lastBackslash = fstrrchr(filename, '\\');
|
||||
lastSlash = max(lastSlash, lastBackslash);
|
||||
if (lastSlash > lastPeriod) return fstring();
|
||||
|
||||
fstrlower(lastPeriod + 1);
|
||||
return fstring(lastPeriod + 1);
|
||||
}
|
||||
|
||||
// For a relative path, extract the list of the individual paths that must be traversed to get to the file.
|
||||
void FUFileManager::ExtractPathStack(const fstring& name, FStringList& list, bool includeFilename)
|
||||
{
|
||||
list.clear();
|
||||
list.reserve(6);
|
||||
|
||||
fstring split = name;
|
||||
while (split.length() > 0)
|
||||
{
|
||||
// Extract out the next path
|
||||
size_t slashIndex = split.find_first_of('/');
|
||||
size_t bslashIndex = split.find_first_of('\\');
|
||||
size_t pathSeparator;
|
||||
if (slashIndex != fstring::npos && bslashIndex != fstring::npos) pathSeparator = min(slashIndex, bslashIndex);
|
||||
else if (bslashIndex != fstring::npos) pathSeparator = bslashIndex;
|
||||
else if (slashIndex != fstring::npos) pathSeparator = slashIndex;
|
||||
else
|
||||
{
|
||||
if (includeFilename) list.push_back(split);
|
||||
break;
|
||||
}
|
||||
|
||||
list.push_back(split.substr(0, pathSeparator));
|
||||
split = split.substr(pathSeparator + 1, split.length() - pathSeparator - 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Make a file path relative/absolute
|
||||
fstring FUFileManager::MakeFilePathAbsolute(const fstring& _filePath)
|
||||
{
|
||||
fstring filePath = _filePath;
|
||||
if ((filePath.size() > 1 && (filePath[0] == '/' || filePath[0] == '\\')) ||
|
||||
(filePath.size() > 2 && (filePath[1] == ':' || filePath[1] == '|')))
|
||||
{
|
||||
// Already an absolute filepath
|
||||
}
|
||||
else
|
||||
{
|
||||
// Relative file path.
|
||||
FStringList documentPaths, localPaths;
|
||||
ExtractPathStack(pathStack.back(), documentPaths, true);
|
||||
ExtractPathStack(filePath, localPaths, true);
|
||||
for (FStringList::iterator it = localPaths.begin(); it != localPaths.end(); ++it)
|
||||
{
|
||||
// Look for special relative path tokens: '.' and '..'
|
||||
if ((*it) == FC(".")) {} // do nothing
|
||||
else if ((*it) == FC("..")) { documentPaths.pop_back(); } // pop one path out
|
||||
else { documentPaths.push_back(*it); } // traverse this path
|
||||
}
|
||||
|
||||
// Recreate the absolute filename
|
||||
filePath.clear();
|
||||
for (FStringList::iterator it = documentPaths.begin(); it != documentPaths.end(); ++it)
|
||||
{
|
||||
if (!filePath.empty()) filePath.push_back('/');
|
||||
filePath += (*it);
|
||||
}
|
||||
|
||||
if (filePath.size() < 2 || (filePath[1] != ':' && filePath[1] != '|'))
|
||||
{
|
||||
filePath.insert(0, '/');
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
std::replace(filePath.begin(), filePath.end(), '/', '\\');
|
||||
#endif // WIN32
|
||||
|
||||
return filePath;
|
||||
}
|
||||
|
||||
fstring FUFileManager::MakeFilePathRelative(const fstring& _filePath)
|
||||
{
|
||||
fstring filePath = _filePath;
|
||||
if (!filePath.empty() && filePath[0] != '.')
|
||||
{
|
||||
// First, ensure we have an absolute file path
|
||||
filePath = MakeFilePathAbsolute(_filePath);
|
||||
|
||||
// Relative file path.
|
||||
FStringList documentPaths, localPaths;
|
||||
ExtractPathStack(pathStack.back(), documentPaths, true);
|
||||
ExtractPathStack(filePath, localPaths, true);
|
||||
|
||||
// Extract the filename from the path stack
|
||||
fstring filename = localPaths.back();
|
||||
localPaths.pop_back();
|
||||
|
||||
// Look for commonality in the path stacks
|
||||
size_t documentPathCount = documentPaths.size();
|
||||
size_t filePathCount = localPaths.size();
|
||||
size_t matchIndex = 0;
|
||||
for (; matchIndex < filePathCount && matchIndex < documentPathCount; ++matchIndex)
|
||||
{
|
||||
if (fstricmp(documentPaths[matchIndex].c_str(), localPaths[matchIndex].c_str()) != 0) break;
|
||||
}
|
||||
|
||||
if (matchIndex != 0)
|
||||
{
|
||||
// There is some similar part, so generate the relative filename
|
||||
fstring relativePath;
|
||||
|
||||
if (documentPathCount > matchIndex)
|
||||
{
|
||||
// Backtrack the document's path
|
||||
for (size_t i = matchIndex; i < documentPathCount; ++i)
|
||||
{
|
||||
relativePath += fstring(FC("../"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Start at the document's root folder
|
||||
relativePath = FC("./");
|
||||
}
|
||||
|
||||
// Add the file's relative path
|
||||
for (size_t i = matchIndex; i < filePathCount; ++i)
|
||||
{
|
||||
relativePath += filePath[i] + fstring(FC("/"));
|
||||
}
|
||||
filePath = relativePath + filename;
|
||||
}
|
||||
}
|
||||
return filePath;
|
||||
}
|
||||
Reference in New Issue
Block a user