vrshoot
diff libs/assimp/FileSystemFilter.h @ 0:b2f14e535253
initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 01 Feb 2014 19:58:19 +0200 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/libs/assimp/FileSystemFilter.h Sat Feb 01 19:58:19 2014 +0200 1.3 @@ -0,0 +1,298 @@ 1.4 +/* 1.5 +Open Asset Import Library (assimp) 1.6 +---------------------------------------------------------------------- 1.7 + 1.8 +Copyright (c) 2006-2008, assimp team 1.9 +All rights reserved. 1.10 + 1.11 +Redistribution and use of this software in source and binary forms, 1.12 +with or without modification, are permitted provided that the 1.13 +following conditions are met: 1.14 + 1.15 +* Redistributions of source code must retain the above 1.16 + copyright notice, this list of conditions and the 1.17 + following disclaimer. 1.18 + 1.19 +* Redistributions in binary form must reproduce the above 1.20 + copyright notice, this list of conditions and the 1.21 + following disclaimer in the documentation and/or other 1.22 + materials provided with the distribution. 1.23 + 1.24 +* Neither the name of the assimp team, nor the names of its 1.25 + contributors may be used to endorse or promote products 1.26 + derived from this software without specific prior 1.27 + written permission of the assimp team. 1.28 + 1.29 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.30 +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.31 +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1.32 +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1.33 +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1.34 +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1.35 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.36 +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.37 +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.38 +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1.39 +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.40 + 1.41 +---------------------------------------------------------------------- 1.42 +*/ 1.43 + 1.44 +/** @file FileSystemFilter.h 1.45 + * Implements a filter system to filter calls to Exists() and Open() 1.46 + * in order to improve the sucess rate of file opening ... 1.47 + */ 1.48 +#ifndef AI_FILESYSTEMFILTER_H_INC 1.49 +#define AI_FILESYSTEMFILTER_H_INC 1.50 + 1.51 +#include "assimp/IOSystem.hpp" 1.52 +#include "fast_atof.h" 1.53 +#include "ParsingUtils.h" 1.54 +namespace Assimp { 1.55 + 1.56 +inline bool IsHex(char s) { 1.57 + return (s>='0' && s<='9') || (s>='a' && s<='f') || (s>='A' && s<='F'); 1.58 +} 1.59 + 1.60 +// --------------------------------------------------------------------------- 1.61 +/** File system filter 1.62 + */ 1.63 +class FileSystemFilter : public IOSystem 1.64 +{ 1.65 +public: 1.66 + /** Constructor. */ 1.67 + FileSystemFilter(const std::string& file, IOSystem* old) 1.68 + : wrapped (old) 1.69 + , src_file (file) 1.70 + , sep(wrapped->getOsSeparator()) 1.71 + { 1.72 + ai_assert(NULL != wrapped); 1.73 + 1.74 + // Determine base directory 1.75 + base = src_file; 1.76 + std::string::size_type ss2; 1.77 + if (std::string::npos != (ss2 = base.find_last_of("\\/"))) { 1.78 + base.erase(ss2,base.length()-ss2); 1.79 + } 1.80 + else { 1.81 + base = ""; 1.82 + // return; 1.83 + } 1.84 + 1.85 + // make sure the directory is terminated properly 1.86 + char s; 1.87 + 1.88 + if (base.length() == 0) { 1.89 + base = "."; 1.90 + base += getOsSeparator(); 1.91 + } 1.92 + else if ((s = *(base.end()-1)) != '\\' && s != '/') { 1.93 + base += getOsSeparator(); 1.94 + } 1.95 + 1.96 + DefaultLogger::get()->info("Import root directory is \'" + base + "\'"); 1.97 + } 1.98 + 1.99 + /** Destructor. */ 1.100 + ~FileSystemFilter() 1.101 + { 1.102 + // haha 1.103 + } 1.104 + 1.105 + // ------------------------------------------------------------------- 1.106 + /** Tests for the existence of a file at the given path. */ 1.107 + bool Exists( const char* pFile) const 1.108 + { 1.109 + std::string tmp = pFile; 1.110 + 1.111 + // Currently this IOSystem is also used to open THE ONE FILE. 1.112 + if (tmp != src_file) { 1.113 + BuildPath(tmp); 1.114 + Cleanup(tmp); 1.115 + } 1.116 + 1.117 + return wrapped->Exists(tmp); 1.118 + } 1.119 + 1.120 + // ------------------------------------------------------------------- 1.121 + /** Returns the directory separator. */ 1.122 + char getOsSeparator() const 1.123 + { 1.124 + return sep; 1.125 + } 1.126 + 1.127 + // ------------------------------------------------------------------- 1.128 + /** Open a new file with a given path. */ 1.129 + IOStream* Open( const char* pFile, const char* pMode = "rb") 1.130 + { 1.131 + ai_assert(pFile); 1.132 + ai_assert(pMode); 1.133 + 1.134 + // First try the unchanged path 1.135 + IOStream* s = wrapped->Open(pFile,pMode); 1.136 + 1.137 + if (!s) { 1.138 + std::string tmp = pFile; 1.139 + 1.140 + // Try to convert between absolute and relative paths 1.141 + BuildPath(tmp); 1.142 + s = wrapped->Open(tmp,pMode); 1.143 + 1.144 + if (!s) { 1.145 + // Finally, look for typical issues with paths 1.146 + // and try to correct them. This is our last 1.147 + // resort. 1.148 + tmp = pFile; 1.149 + Cleanup(tmp); 1.150 + BuildPath(tmp); 1.151 + s = wrapped->Open(tmp,pMode); 1.152 + } 1.153 + } 1.154 + 1.155 + return s; 1.156 + } 1.157 + 1.158 + // ------------------------------------------------------------------- 1.159 + /** Closes the given file and releases all resources associated with it. */ 1.160 + void Close( IOStream* pFile) 1.161 + { 1.162 + return wrapped->Close(pFile); 1.163 + } 1.164 + 1.165 + // ------------------------------------------------------------------- 1.166 + /** Compare two paths */ 1.167 + bool ComparePaths (const char* one, const char* second) const 1.168 + { 1.169 + return wrapped->ComparePaths (one,second); 1.170 + } 1.171 + 1.172 +private: 1.173 + 1.174 + // ------------------------------------------------------------------- 1.175 + /** Build a valid path from a given relative or absolute path. 1.176 + */ 1.177 + void BuildPath (std::string& in) const 1.178 + { 1.179 + // if we can already access the file, great. 1.180 + if (in.length() < 3 || wrapped->Exists(in)) { 1.181 + return; 1.182 + } 1.183 + 1.184 + // Determine whether this is a relative path (Windows-specific - most assets are packaged on Windows). 1.185 + if (in[1] != ':') { 1.186 + 1.187 + // append base path and try 1.188 + const std::string tmp = base + in; 1.189 + if (wrapped->Exists(tmp)) { 1.190 + in = tmp; 1.191 + return; 1.192 + } 1.193 + } 1.194 + 1.195 + // Chop of the file name and look in the model directory, if 1.196 + // this fails try all sub paths of the given path, i.e. 1.197 + // if the given path is foo/bar/something.lwo, try 1.198 + // <base>/something.lwo 1.199 + // <base>/bar/something.lwo 1.200 + // <base>/foo/bar/something.lwo 1.201 + std::string::size_type pos = in.rfind('/'); 1.202 + if (std::string::npos == pos) { 1.203 + pos = in.rfind('\\'); 1.204 + } 1.205 + 1.206 + if (std::string::npos != pos) { 1.207 + std::string tmp; 1.208 + std::string::size_type last_dirsep = std::string::npos; 1.209 + 1.210 + while(true) { 1.211 + tmp = base; 1.212 + tmp += sep; 1.213 + 1.214 + std::string::size_type dirsep = in.rfind('/', last_dirsep); 1.215 + if (std::string::npos == dirsep) { 1.216 + dirsep = in.rfind('\\', last_dirsep); 1.217 + } 1.218 + 1.219 + if (std::string::npos == dirsep || dirsep == 0) { 1.220 + // we did try this already. 1.221 + break; 1.222 + } 1.223 + 1.224 + last_dirsep = dirsep-1; 1.225 + 1.226 + tmp += in.substr(dirsep+1, in.length()-pos); 1.227 + if (wrapped->Exists(tmp)) { 1.228 + in = tmp; 1.229 + return; 1.230 + } 1.231 + } 1.232 + } 1.233 + 1.234 + // hopefully the underlying file system has another few tricks to access this file ... 1.235 + } 1.236 + 1.237 + // ------------------------------------------------------------------- 1.238 + /** Cleanup the given path 1.239 + */ 1.240 + void Cleanup (std::string& in) const 1.241 + { 1.242 + char last = 0; 1.243 + if(in.empty()) { 1.244 + return; 1.245 + } 1.246 + 1.247 + // Remove a very common issue when we're parsing file names: spaces at the 1.248 + // beginning of the path. 1.249 + std::string::iterator it = in.begin(); 1.250 + while (IsSpaceOrNewLine( *it ))++it; 1.251 + if (it != in.begin()) { 1.252 + in.erase(in.begin(),it+1); 1.253 + } 1.254 + 1.255 + const char sep = getOsSeparator(); 1.256 + for (it = in.begin(); it != in.end(); ++it) { 1.257 + // Exclude :// and \\, which remain untouched. 1.258 + // https://sourceforge.net/tracker/?func=detail&aid=3031725&group_id=226462&atid=1067632 1.259 + if ( !strncmp(&*it, "://", 3 )) { 1.260 + it += 3; 1.261 + continue; 1.262 + } 1.263 + if (it == in.begin() && !strncmp(&*it, "\\\\", 2)) { 1.264 + it += 2; 1.265 + continue; 1.266 + } 1.267 + 1.268 + // Cleanup path delimiters 1.269 + if (*it == '/' || (*it) == '\\') { 1.270 + *it = sep; 1.271 + 1.272 + // And we're removing double delimiters, frequent issue with 1.273 + // incorrectly composited paths ... 1.274 + if (last == *it) { 1.275 + it = in.erase(it); 1.276 + --it; 1.277 + } 1.278 + } 1.279 + else if (*it == '%' && in.end() - it > 2) { 1.280 + 1.281 + // Hex sequence in URIs 1.282 + if( IsHex((&*it)[0]) && IsHex((&*it)[1]) ) { 1.283 + *it = HexOctetToDecimal(&*it); 1.284 + it = in.erase(it+1,it+2); 1.285 + --it; 1.286 + } 1.287 + } 1.288 + 1.289 + last = *it; 1.290 + } 1.291 + } 1.292 + 1.293 +private: 1.294 + IOSystem* wrapped; 1.295 + std::string src_file, base; 1.296 + char sep; 1.297 +}; 1.298 + 1.299 +} //!ns Assimp 1.300 + 1.301 +#endif //AI_DEFAULTIOSYSTEM_H_INC