nuclear@0: /* nuclear@0: --------------------------------------------------------------------------- nuclear@0: Open Asset Import Library (assimp) nuclear@0: --------------------------------------------------------------------------- nuclear@0: nuclear@0: Copyright (c) 2006-2018, assimp team nuclear@0: nuclear@0: nuclear@0: nuclear@0: All rights reserved. nuclear@0: nuclear@0: Redistribution and use of this software in source and binary forms, nuclear@0: with or without modification, are permitted provided that the following nuclear@0: conditions are met: nuclear@0: nuclear@0: * Redistributions of source code must retain the above nuclear@0: copyright notice, this list of conditions and the nuclear@0: following disclaimer. nuclear@0: nuclear@0: * Redistributions in binary form must reproduce the above nuclear@0: copyright notice, this list of conditions and the nuclear@0: following disclaimer in the documentation and/or other nuclear@0: materials provided with the distribution. nuclear@0: nuclear@0: * Neither the name of the assimp team, nor the names of its nuclear@0: contributors may be used to endorse or promote products nuclear@0: derived from this software without specific prior nuclear@0: written permission of the assimp team. nuclear@0: nuclear@0: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS nuclear@0: "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT nuclear@0: LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR nuclear@0: A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT nuclear@0: OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, nuclear@0: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT nuclear@0: LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, nuclear@0: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY nuclear@0: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT nuclear@0: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE nuclear@0: OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. nuclear@0: --------------------------------------------------------------------------- nuclear@0: */ nuclear@0: nuclear@0: /** @file IOSystem.hpp nuclear@0: * @brief File system wrapper for C++. Inherit this class to supply nuclear@0: * custom file handling logic to the Import library. nuclear@0: */ nuclear@0: nuclear@0: #pragma once nuclear@0: #ifndef AI_IOSYSTEM_H_INC nuclear@0: #define AI_IOSYSTEM_H_INC nuclear@0: nuclear@0: #ifndef __cplusplus nuclear@0: # error This header requires C++ to be used. aiFileIO.h is the \ nuclear@0: corresponding C interface. nuclear@0: #endif nuclear@0: nuclear@0: #include "types.h" nuclear@0: nuclear@0: #ifdef _WIN32 nuclear@0: # include nuclear@0: # include nuclear@0: # include nuclear@0: #else nuclear@0: # include nuclear@0: # include nuclear@0: # include nuclear@0: #endif // _WIN32 nuclear@0: nuclear@0: #include nuclear@0: nuclear@0: namespace Assimp { nuclear@0: nuclear@0: class IOStream; nuclear@0: nuclear@0: // --------------------------------------------------------------------------- nuclear@0: /** @brief CPP-API: Interface to the file system. nuclear@0: * nuclear@0: * Derive an own implementation from this interface to supply custom file handling nuclear@0: * to the importer library. If you implement this interface, you also want to nuclear@0: * supply a custom implementation for IOStream. nuclear@0: * nuclear@0: * @see Importer::SetIOHandler() nuclear@0: */ nuclear@0: class ASSIMP_API IOSystem nuclear@0: #ifndef SWIG nuclear@0: : public Intern::AllocateFromAssimpHeap nuclear@0: #endif nuclear@0: { nuclear@0: public: nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: /** @brief Default constructor. nuclear@0: * nuclear@0: * Create an instance of your derived class and assign it to an nuclear@0: * #Assimp::Importer instance by calling Importer::SetIOHandler(). nuclear@0: */ nuclear@0: IOSystem() AI_NO_EXCEPT; nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: /** @brief Virtual destructor. nuclear@0: * nuclear@0: * It is safe to be called from within DLL Assimp, we're constructed nuclear@0: * on Assimp's heap. nuclear@0: */ nuclear@0: virtual ~IOSystem(); nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: /** @brief For backward compatibility nuclear@0: * @see Exists(const char*) nuclear@0: */ nuclear@0: AI_FORCE_INLINE bool Exists( const std::string& pFile) const; nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: /** @brief Tests for the existence of a file at the given path. nuclear@0: * nuclear@0: * @param pFile Path to the file nuclear@0: * @return true if there is a file with this path, else false. nuclear@0: */ nuclear@0: virtual bool Exists( const char* pFile) const = 0; nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: /** @brief Returns the system specific directory separator nuclear@0: * @return System specific directory separator nuclear@0: */ nuclear@0: virtual char getOsSeparator() const = 0; nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: /** @brief Open a new file with a given path. nuclear@0: * nuclear@0: * When the access to the file is finished, call Close() to release nuclear@0: * all associated resources (or the virtual dtor of the IOStream). nuclear@0: * nuclear@0: * @param pFile Path to the file nuclear@0: * @param pMode Desired file I/O mode. Required are: "wb", "w", "wt", nuclear@0: * "rb", "r", "rt". nuclear@0: * nuclear@0: * @return New IOStream interface allowing the lib to access nuclear@0: * the underlying file. nuclear@0: * @note When implementing this class to provide custom IO handling, nuclear@0: * you probably have to supply an own implementation of IOStream as well. nuclear@0: */ nuclear@0: virtual IOStream* Open(const char* pFile, nuclear@0: const char* pMode = "rb") = 0; nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: /** @brief For backward compatibility nuclear@0: * @see Open(const char*, const char*) nuclear@0: */ nuclear@0: inline IOStream* Open(const std::string& pFile, nuclear@0: const std::string& pMode = std::string("rb")); nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: /** @brief Closes the given file and releases all resources nuclear@0: * associated with it. nuclear@0: * @param pFile The file instance previously created by Open(). nuclear@0: */ nuclear@0: virtual void Close( IOStream* pFile) = 0; nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: /** @brief Compares two paths and check whether the point to nuclear@0: * identical files. nuclear@0: * nuclear@0: * The dummy implementation of this virtual member performs a nuclear@0: * case-insensitive comparison of the given strings. The default IO nuclear@0: * system implementation uses OS mechanisms to convert relative into nuclear@0: * absolute paths, so the result can be trusted. nuclear@0: * @param one First file nuclear@0: * @param second Second file nuclear@0: * @return true if the paths point to the same file. The file needn't nuclear@0: * be existing, however. nuclear@0: */ nuclear@0: virtual bool ComparePaths (const char* one, nuclear@0: const char* second) const; nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: /** @brief For backward compatibility nuclear@0: * @see ComparePaths(const char*, const char*) nuclear@0: */ nuclear@0: inline bool ComparePaths (const std::string& one, nuclear@0: const std::string& second) const; nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: /** @brief Pushes a new directory onto the directory stack. nuclear@0: * @param path Path to push onto the stack. nuclear@0: * @return True, when push was successful, false if path is empty. nuclear@0: */ nuclear@0: virtual bool PushDirectory( const std::string &path ); nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: /** @brief Returns the top directory from the stack. nuclear@0: * @return The directory on the top of the stack. nuclear@0: * Returns empty when no directory was pushed to the stack. nuclear@0: */ nuclear@0: virtual const std::string &CurrentDirectory() const; nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: /** @brief Returns the number of directories stored on the stack. nuclear@0: * @return The number of directories of the stack. nuclear@0: */ nuclear@0: virtual size_t StackSize() const; nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: /** @brief Pops the top directory from the stack. nuclear@0: * @return True, when a directory was on the stack. False if no nuclear@0: * directory was on the stack. nuclear@0: */ nuclear@0: virtual bool PopDirectory(); nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: /** @brief CReates an new directory at the given path. nuclear@0: * @param path [in] The path to create. nuclear@0: * @return True, when a directory was created. False if the directory nuclear@0: * cannot be created. nuclear@0: */ nuclear@0: virtual bool CreateDirectory( const std::string &path ); nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: /** @brief Will change the current directory to the given path. nuclear@0: * @param path [in] The path to change to. nuclear@0: * @return True, when the directory has changed successfully. nuclear@0: */ nuclear@0: virtual bool ChangeDirectory( const std::string &path ); nuclear@0: nuclear@0: virtual bool DeleteFile( const std::string &file ); nuclear@0: nuclear@0: private: nuclear@0: std::vector m_pathStack; nuclear@0: }; nuclear@0: nuclear@0: // ---------------------------------------------------------------------------- nuclear@0: AI_FORCE_INLINE nuclear@0: IOSystem::IOSystem() AI_NO_EXCEPT nuclear@0: : m_pathStack() { nuclear@0: // empty nuclear@0: } nuclear@0: nuclear@0: // ---------------------------------------------------------------------------- nuclear@0: AI_FORCE_INLINE nuclear@0: IOSystem::~IOSystem() { nuclear@0: // empty nuclear@0: } nuclear@0: nuclear@0: // ---------------------------------------------------------------------------- nuclear@0: // For compatibility, the interface of some functions taking a std::string was nuclear@0: // changed to const char* to avoid crashes between binary incompatible STL nuclear@0: // versions. This code her is inlined, so it shouldn't cause any problems. nuclear@0: // ---------------------------------------------------------------------------- nuclear@0: nuclear@0: // ---------------------------------------------------------------------------- nuclear@0: AI_FORCE_INLINE nuclear@0: IOStream* IOSystem::Open(const std::string& pFile, const std::string& pMode) { nuclear@0: // NOTE: nuclear@0: // For compatibility, interface was changed to const char* to nuclear@0: // avoid crashes between binary incompatible STL versions nuclear@0: return Open(pFile.c_str(),pMode.c_str()); nuclear@0: } nuclear@0: nuclear@0: // ---------------------------------------------------------------------------- nuclear@0: AI_FORCE_INLINE nuclear@0: bool IOSystem::Exists( const std::string& pFile) const { nuclear@0: // NOTE: nuclear@0: // For compatibility, interface was changed to const char* to nuclear@0: // avoid crashes between binary incompatible STL versions nuclear@0: return Exists(pFile.c_str()); nuclear@0: } nuclear@0: nuclear@0: // ---------------------------------------------------------------------------- nuclear@0: AI_FORCE_INLINE nuclear@0: bool IOSystem::ComparePaths (const std::string& one, const std::string& second) const { nuclear@0: // NOTE: nuclear@0: // For compatibility, interface was changed to const char* to nuclear@0: // avoid crashes between binary incompatible STL versions nuclear@0: return ComparePaths(one.c_str(),second.c_str()); nuclear@0: } nuclear@0: nuclear@0: // ---------------------------------------------------------------------------- nuclear@0: AI_FORCE_INLINE nuclear@0: bool IOSystem::PushDirectory( const std::string &path ) { nuclear@0: if ( path.empty() ) { nuclear@0: return false; nuclear@0: } nuclear@0: nuclear@0: m_pathStack.push_back( path ); nuclear@0: nuclear@0: return true; nuclear@0: } nuclear@0: nuclear@0: // ---------------------------------------------------------------------------- nuclear@0: AI_FORCE_INLINE nuclear@0: const std::string &IOSystem::CurrentDirectory() const { nuclear@0: if ( m_pathStack.empty() ) { nuclear@0: static const std::string Dummy(""); nuclear@0: return Dummy; nuclear@0: } nuclear@0: return m_pathStack[ m_pathStack.size()-1 ]; nuclear@0: } nuclear@0: nuclear@0: // ---------------------------------------------------------------------------- nuclear@0: AI_FORCE_INLINE nuclear@0: size_t IOSystem::StackSize() const { nuclear@0: return m_pathStack.size(); nuclear@0: } nuclear@0: nuclear@0: // ---------------------------------------------------------------------------- nuclear@0: AI_FORCE_INLINE nuclear@0: bool IOSystem::PopDirectory() { nuclear@0: if ( m_pathStack.empty() ) { nuclear@0: return false; nuclear@0: } nuclear@0: nuclear@0: m_pathStack.pop_back(); nuclear@0: nuclear@0: return true; nuclear@0: } nuclear@0: nuclear@0: // ---------------------------------------------------------------------------- nuclear@0: AI_FORCE_INLINE nuclear@0: bool IOSystem::CreateDirectory( const std::string &path ) { nuclear@0: if ( path.empty() ) { nuclear@0: return false; nuclear@0: } nuclear@0: nuclear@0: #ifdef _WIN32 nuclear@0: return 0 != ::_mkdir( path.c_str() ); nuclear@0: #else nuclear@0: return 0 != ::mkdir( path.c_str(), 0777 ); nuclear@0: #endif // _WIN32 nuclear@0: } nuclear@0: nuclear@0: // ---------------------------------------------------------------------------- nuclear@0: AI_FORCE_INLINE nuclear@0: bool IOSystem::ChangeDirectory( const std::string &path ) { nuclear@0: if ( path.empty() ) { nuclear@0: return false; nuclear@0: } nuclear@0: nuclear@0: #ifdef _WIN32 nuclear@0: return 0 != ::_chdir( path.c_str() ); nuclear@0: #else nuclear@0: return 0 != ::chdir( path.c_str() ); nuclear@0: #endif // _WIN32 nuclear@0: } nuclear@0: nuclear@0: nuclear@0: // ---------------------------------------------------------------------------- nuclear@0: AI_FORCE_INLINE nuclear@0: bool IOSystem::DeleteFile( const std::string &file ) { nuclear@0: if ( file.empty() ) { nuclear@0: return false; nuclear@0: } nuclear@0: const int retCode( ::remove( file.c_str() ) ); nuclear@0: return ( 0 == retCode ); nuclear@0: } nuclear@0: } //!ns Assimp nuclear@0: nuclear@0: #endif //AI_IOSYSTEM_H_INC