Merge pull request #1805 from assimp/develop_kimkulling

Update FileSystemFilter.h
pull/1793/head
Kim Kulling 2018-02-23 18:27:29 +01:00 committed by GitHub
commit 259fd2df2d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 80 additions and 84 deletions

View File

@ -42,13 +42,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* Implements a filter system to filter calls to Exists() and Open() * Implements a filter system to filter calls to Exists() and Open()
* in order to improve the success rate of file opening ... * in order to improve the success rate of file opening ...
*/ */
#pragma once
#ifndef AI_FILESYSTEMFILTER_H_INC #ifndef AI_FILESYSTEMFILTER_H_INC
#define AI_FILESYSTEMFILTER_H_INC #define AI_FILESYSTEMFILTER_H_INC
#include "../include/assimp/IOSystem.hpp" #include <assimp/IOSystem.hpp>
#include "../include/assimp/DefaultLogger.hpp" #include <assimp/DefaultLogger.hpp>
#include "../include/assimp/fast_atof.h" #include <assimp/fast_atof.h>
#include "../include/assimp/ParsingUtils.h" #include <assimp/ParsingUtils.h>
namespace Assimp { namespace Assimp {
@ -64,90 +65,89 @@ class FileSystemFilter : public IOSystem
public: public:
/** Constructor. */ /** Constructor. */
FileSystemFilter(const std::string& file, IOSystem* old) FileSystemFilter(const std::string& file, IOSystem* old)
: wrapped (old) : mWrapped (old)
, src_file (file) , mSrc_file(file)
, sep(wrapped->getOsSeparator()) , sep(mWrapped->getOsSeparator()) {
{ ai_assert(nullptr != mWrapped);
ai_assert(NULL != wrapped);
// Determine base directory // Determine base directory
base = src_file; mBase = mSrc_file;
std::string::size_type ss2; std::string::size_type ss2;
if (std::string::npos != (ss2 = base.find_last_of("\\/"))) { if (std::string::npos != (ss2 = mBase.find_last_of("\\/"))) {
base.erase(ss2,base.length()-ss2); mBase.erase(ss2,mBase.length()-ss2);
} } else {
else { mBase = "";
base = "";
// return;
} }
// make sure the directory is terminated properly // make sure the directory is terminated properly
char s; char s;
if (base.length() == 0) { if ( mBase.empty() ) {
base = "."; mBase = ".";
base += getOsSeparator(); mBase += getOsSeparator();
} } else if ((s = *(mBase.end()-1)) != '\\' && s != '/') {
else if ((s = *(base.end()-1)) != '\\' && s != '/') { mBase += getOsSeparator();
base += getOsSeparator();
} }
DefaultLogger::get()->info("Import root directory is \'" + base + "\'"); DefaultLogger::get()->info("Import root directory is \'" + mBase + "\'");
} }
/** Destructor. */ /** Destructor. */
~FileSystemFilter() ~FileSystemFilter() {
{ // empty
// haha
} }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Tests for the existence of a file at the given path. */ /** Tests for the existence of a file at the given path. */
bool Exists( const char* pFile) const bool Exists( const char* pFile) const {
{ ai_assert( nullptr != mWrapped );
std::string tmp = pFile; std::string tmp = pFile;
// Currently this IOSystem is also used to open THE ONE FILE. // Currently this IOSystem is also used to open THE ONE FILE.
if (tmp != src_file) { if (tmp != mSrc_file) {
BuildPath(tmp); BuildPath(tmp);
Cleanup(tmp); Cleanup(tmp);
} }
return wrapped->Exists(tmp); return mWrapped->Exists(tmp);
} }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Returns the directory separator. */ /** Returns the directory separator. */
char getOsSeparator() const char getOsSeparator() const {
{
return sep; return sep;
} }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Open a new file with a given path. */ /** Open a new file with a given path. */
IOStream* Open( const char* pFile, const char* pMode = "rb") IOStream* Open( const char* pFile, const char* pMode = "rb") {
{ ai_assert( nullptr != mWrapped );
ai_assert(pFile); if ( nullptr == pFile || nullptr == pMode ) {
ai_assert(pMode); return nullptr;
}
ai_assert( nullptr != pFile );
ai_assert( nullptr != pMode );
// First try the unchanged path // First try the unchanged path
IOStream* s = wrapped->Open(pFile,pMode); IOStream* s = mWrapped->Open(pFile,pMode);
if (!s) { if (nullptr == s) {
std::string tmp = pFile; std::string tmp = pFile;
// Try to convert between absolute and relative paths // Try to convert between absolute and relative paths
BuildPath(tmp); BuildPath(tmp);
s = wrapped->Open(tmp,pMode); s = mWrapped->Open(tmp,pMode);
if (!s) { if (nullptr == s) {
// Finally, look for typical issues with paths // Finally, look for typical issues with paths
// and try to correct them. This is our last // and try to correct them. This is our last
// resort. // resort.
tmp = pFile; tmp = pFile;
Cleanup(tmp); Cleanup(tmp);
BuildPath(tmp); BuildPath(tmp);
s = wrapped->Open(tmp,pMode); s = mWrapped->Open(tmp,pMode);
} }
} }
@ -156,76 +156,75 @@ public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Closes the given file and releases all resources associated with it. */ /** Closes the given file and releases all resources associated with it. */
void Close( IOStream* pFile) void Close( IOStream* pFile) {
{ ai_assert( nullptr != mWrapped );
return wrapped->Close(pFile); return mWrapped->Close(pFile);
} }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Compare two paths */ /** Compare two paths */
bool ComparePaths (const char* one, const char* second) const bool ComparePaths (const char* one, const char* second) const {
{ ai_assert( nullptr != mWrapped );
return wrapped->ComparePaths (one,second); return mWrapped->ComparePaths (one,second);
} }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Pushes a new directory onto the directory stack. */ /** Pushes a new directory onto the directory stack. */
bool PushDirectory(const std::string &path) bool PushDirectory(const std::string &path ) {
{ ai_assert( nullptr != mWrapped );
return wrapped->PushDirectory(path); return mWrapped->PushDirectory(path);
} }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Returns the top directory from the stack. */ /** Returns the top directory from the stack. */
const std::string &CurrentDirectory() const const std::string &CurrentDirectory() const {
{ ai_assert( nullptr != mWrapped );
return wrapped->CurrentDirectory(); return mWrapped->CurrentDirectory();
} }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Returns the number of directories stored on the stack. */ /** Returns the number of directories stored on the stack. */
size_t StackSize() const size_t StackSize() const {
{ ai_assert( nullptr != mWrapped );
return wrapped->StackSize(); return mWrapped->StackSize();
} }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Pops the top directory from the stack. */ /** Pops the top directory from the stack. */
bool PopDirectory() bool PopDirectory() {
{ ai_assert( nullptr != mWrapped );
return wrapped->PopDirectory(); return mWrapped->PopDirectory();
} }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Creates an new directory at the given path. */ /** Creates an new directory at the given path. */
bool CreateDirectory(const std::string &path) bool CreateDirectory(const std::string &path) {
{ ai_assert( nullptr != mWrapped );
return wrapped->CreateDirectory(path); return mWrapped->CreateDirectory(path);
} }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Will change the current directory to the given path. */ /** Will change the current directory to the given path. */
bool ChangeDirectory(const std::string &path) bool ChangeDirectory(const std::string &path) {
{ ai_assert( nullptr != mWrapped );
return wrapped->ChangeDirectory(path); return mWrapped->ChangeDirectory(path);
} }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Delete file. */ /** Delete file. */
bool DeleteFile(const std::string &file) bool DeleteFile(const std::string &file) {
{ ai_assert( nullptr != mWrapped );
return wrapped->DeleteFile(file); return mWrapped->DeleteFile(file);
} }
private: private:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Build a valid path from a given relative or absolute path. /** Build a valid path from a given relative or absolute path.
*/ */
void BuildPath (std::string& in) const void BuildPath (std::string& in) const {
{ ai_assert( nullptr != mWrapped );
// if we can already access the file, great. // if we can already access the file, great.
if (in.length() < 3 || wrapped->Exists(in)) { if (in.length() < 3 || mWrapped->Exists(in)) {
return; return;
} }
@ -233,8 +232,8 @@ private:
if (in[1] != ':') { if (in[1] != ':') {
// append base path and try // append base path and try
const std::string tmp = base + in; const std::string tmp = mBase + in;
if (wrapped->Exists(tmp)) { if (mWrapped->Exists(tmp)) {
in = tmp; in = tmp;
return; return;
} }
@ -256,7 +255,7 @@ private:
std::string::size_type last_dirsep = std::string::npos; std::string::size_type last_dirsep = std::string::npos;
while(true) { while(true) {
tmp = base; tmp = mBase;
tmp += sep; tmp += sep;
std::string::size_type dirsep = in.rfind('/', last_dirsep); std::string::size_type dirsep = in.rfind('/', last_dirsep);
@ -272,7 +271,7 @@ private:
last_dirsep = dirsep-1; last_dirsep = dirsep-1;
tmp += in.substr(dirsep+1, in.length()-pos); tmp += in.substr(dirsep+1, in.length()-pos);
if (wrapped->Exists(tmp)) { if (mWrapped->Exists(tmp)) {
in = tmp; in = tmp;
return; return;
} }
@ -285,15 +284,14 @@ private:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Cleanup the given path /** Cleanup the given path
*/ */
void Cleanup (std::string& in) const void Cleanup (std::string& in) const {
{
char last = 0;
if(in.empty()) { if(in.empty()) {
return; return;
} }
// Remove a very common issue when we're parsing file names: spaces at the // Remove a very common issue when we're parsing file names: spaces at the
// beginning of the path. // beginning of the path.
char last = 0;
std::string::iterator it = in.begin(); std::string::iterator it = in.begin();
while (IsSpaceOrNewLine( *it ))++it; while (IsSpaceOrNewLine( *it ))++it;
if (it != in.begin()) { if (it != in.begin()) {
@ -323,9 +321,7 @@ private:
it = in.erase(it); it = in.erase(it);
--it; --it;
} }
} } else if (*it == '%' && in.end() - it > 2) {
else if (*it == '%' && in.end() - it > 2) {
// Hex sequence in URIs // Hex sequence in URIs
if( IsHex((&*it)[0]) && IsHex((&*it)[1]) ) { if( IsHex((&*it)[0]) && IsHex((&*it)[1]) ) {
*it = HexOctetToDecimal(&*it); *it = HexOctetToDecimal(&*it);
@ -339,8 +335,8 @@ private:
} }
private: private:
IOSystem* wrapped; IOSystem *mWrapped;
std::string src_file, base; std::string mSrc_file, mBase;
char sep; char sep;
}; };