1/*
2---------------------------------------------------------------------------
3Open Asset Import Library (assimp)
4---------------------------------------------------------------------------
5
6Copyright (c) 2006-2017, assimp team
7
8
9All rights reserved.
10
11Redistribution and use of this software in source and binary forms,
12with or without modification, are permitted provided that the following
13conditions are met:
14
15* Redistributions of source code must retain the above
16 copyright notice, this list of conditions and the
17 following disclaimer.
18
19* Redistributions in binary form must reproduce the above
20 copyright notice, this list of conditions and the
21 following disclaimer in the documentation and/or other
22 materials provided with the distribution.
23
24* Neither the name of the assimp team, nor the names of its
25 contributors may be used to endorse or promote products
26 derived from this software without specific prior
27 written permission of the assimp team.
28
29THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40---------------------------------------------------------------------------
41*/
42
43/** @file IOSystem.hpp
44 * @brief File system wrapper for C++. Inherit this class to supply
45 * custom file handling logic to the Import library.
46*/
47
48#pragma once
49#ifndef AI_IOSYSTEM_H_INC
50#define AI_IOSYSTEM_H_INC
51
52#ifndef __cplusplus
53# error This header requires C++ to be used. aiFileIO.h is the \
54 corresponding C interface.
55#endif
56
57#include "types.h"
58
59#ifdef _WIN32
60# include <direct.h>
61# include <stdlib.h>
62# include <stdio.h>
63#else
64# include <sys/stat.h>
65# include <sys/types.h>
66# include <unistd.h>
67#endif // _WIN32
68
69#include <vector>
70
71namespace Assimp {
72
73 class IOStream;
74
75// ---------------------------------------------------------------------------
76/** @brief CPP-API: Interface to the file system.
77 *
78 * Derive an own implementation from this interface to supply custom file handling
79 * to the importer library. If you implement this interface, you also want to
80 * supply a custom implementation for IOStream.
81 *
82 * @see Importer::SetIOHandler()
83 */
84class ASSIMP_API IOSystem
85#ifndef SWIG
86 : public Intern::AllocateFromAssimpHeap
87#endif
88{
89public:
90
91 // -------------------------------------------------------------------
92 /** @brief Default constructor.
93 *
94 * Create an instance of your derived class and assign it to an
95 * #Assimp::Importer instance by calling Importer::SetIOHandler().
96 */
97 IOSystem();
98
99 // -------------------------------------------------------------------
100 /** @brief Virtual destructor.
101 *
102 * It is safe to be called from within DLL Assimp, we're constructed
103 * on Assimp's heap.
104 */
105 virtual ~IOSystem();
106
107
108public:
109
110 // -------------------------------------------------------------------
111 /** @brief For backward compatibility
112 * @see Exists(const char*)
113 */
114 AI_FORCE_INLINE bool Exists( const std::string& pFile) const;
115
116 // -------------------------------------------------------------------
117 /** @brief Tests for the existence of a file at the given path.
118 *
119 * @param pFile Path to the file
120 * @return true if there is a file with this path, else false.
121 */
122 virtual bool Exists( const char* pFile) const = 0;
123
124 // -------------------------------------------------------------------
125 /** @brief Returns the system specific directory separator
126 * @return System specific directory separator
127 */
128 virtual char getOsSeparator() const = 0;
129
130 // -------------------------------------------------------------------
131 /** @brief Open a new file with a given path.
132 *
133 * When the access to the file is finished, call Close() to release
134 * all associated resources (or the virtual dtor of the IOStream).
135 *
136 * @param pFile Path to the file
137 * @param pMode Desired file I/O mode. Required are: "wb", "w", "wt",
138 * "rb", "r", "rt".
139 *
140 * @return New IOStream interface allowing the lib to access
141 * the underlying file.
142 * @note When implementing this class to provide custom IO handling,
143 * you probably have to supply an own implementation of IOStream as well.
144 */
145 virtual IOStream* Open(const char* pFile,
146 const char* pMode = "rb") = 0;
147
148 // -------------------------------------------------------------------
149 /** @brief For backward compatibility
150 * @see Open(const char*, const char*)
151 */
152 inline IOStream* Open(const std::string& pFile,
153 const std::string& pMode = std::string("rb"));
154
155 // -------------------------------------------------------------------
156 /** @brief Closes the given file and releases all resources
157 * associated with it.
158 * @param pFile The file instance previously created by Open().
159 */
160 virtual void Close( IOStream* pFile) = 0;
161
162 // -------------------------------------------------------------------
163 /** @brief Compares two paths and check whether the point to
164 * identical files.
165 *
166 * The dummy implementation of this virtual member performs a
167 * case-insensitive comparison of the given strings. The default IO
168 * system implementation uses OS mechanisms to convert relative into
169 * absolute paths, so the result can be trusted.
170 * @param one First file
171 * @param second Second file
172 * @return true if the paths point to the same file. The file needn't
173 * be existing, however.
174 */
175 virtual bool ComparePaths (const char* one,
176 const char* second) const;
177
178 // -------------------------------------------------------------------
179 /** @brief For backward compatibility
180 * @see ComparePaths(const char*, const char*)
181 */
182 inline bool ComparePaths (const std::string& one,
183 const std::string& second) const;
184
185 // -------------------------------------------------------------------
186 /** @brief Pushes a new directory onto the directory stack.
187 * @param path Path to push onto the stack.
188 * @return True, when push was successful, false if path is empty.
189 */
190 virtual bool PushDirectory( const std::string &path );
191
192 // -------------------------------------------------------------------
193 /** @brief Returns the top directory from the stack.
194 * @return The directory on the top of the stack.
195 * Returns empty when no directory was pushed to the stack.
196 */
197 virtual const std::string &CurrentDirectory() const;
198
199 // -------------------------------------------------------------------
200 /** @brief Returns the number of directories stored on the stack.
201 * @return The number of directories of the stack.
202 */
203 virtual size_t StackSize() const;
204
205 // -------------------------------------------------------------------
206 /** @brief Pops the top directory from the stack.
207 * @return True, when a directory was on the stack. False if no
208 * directory was on the stack.
209 */
210 virtual bool PopDirectory();
211
212 // -------------------------------------------------------------------
213 /** @brief CReates an new directory at the given path.
214 * @param path [in] The path to create.
215 * @return True, when a directory was created. False if the directory
216 * cannot be created.
217 */
218 virtual bool CreateDirectory( const std::string &path );
219
220 // -------------------------------------------------------------------
221 /** @brief Will change the current directory to the given path.
222 * @param path [in] The path to change to.
223 * @return True, when the directory has changed successfully.
224 */
225 virtual bool ChangeDirectory( const std::string &path );
226
227 virtual bool DeleteFile( const std::string &file );
228
229private:
230 std::vector<std::string> m_pathStack;
231};
232
233// ----------------------------------------------------------------------------
234AI_FORCE_INLINE
235IOSystem::IOSystem()
236: m_pathStack() {
237 // empty
238}
239
240// ----------------------------------------------------------------------------
241AI_FORCE_INLINE
242IOSystem::~IOSystem() {
243 // empty
244}
245
246// ----------------------------------------------------------------------------
247// For compatibility, the interface of some functions taking a std::string was
248// changed to const char* to avoid crashes between binary incompatible STL
249// versions. This code her is inlined, so it shouldn't cause any problems.
250// ----------------------------------------------------------------------------
251
252// ----------------------------------------------------------------------------
253AI_FORCE_INLINE
254IOStream* IOSystem::Open(const std::string& pFile, const std::string& pMode) {
255 // NOTE:
256 // For compatibility, interface was changed to const char* to
257 // avoid crashes between binary incompatible STL versions
258 return Open(pFile.c_str(),pMode.c_str());
259}
260
261// ----------------------------------------------------------------------------
262AI_FORCE_INLINE
263bool IOSystem::Exists( const std::string& pFile) const {
264 // NOTE:
265 // For compatibility, interface was changed to const char* to
266 // avoid crashes between binary incompatible STL versions
267 return Exists(pFile.c_str());
268}
269
270// ----------------------------------------------------------------------------
271AI_FORCE_INLINE
272bool IOSystem::ComparePaths (const std::string& one, const std::string& second) const {
273 // NOTE:
274 // For compatibility, interface was changed to const char* to
275 // avoid crashes between binary incompatible STL versions
276 return ComparePaths(one.c_str(),second.c_str());
277}
278
279// ----------------------------------------------------------------------------
280AI_FORCE_INLINE
281bool IOSystem::PushDirectory( const std::string &path ) {
282 if ( path.empty() ) {
283 return false;
284 }
285
286 m_pathStack.push_back( path );
287
288 return true;
289}
290
291// ----------------------------------------------------------------------------
292AI_FORCE_INLINE
293const std::string &IOSystem::CurrentDirectory() const {
294 if ( m_pathStack.empty() ) {
295 static const std::string Dummy("");
296 return Dummy;
297 }
298 return m_pathStack[ m_pathStack.size()-1 ];
299}
300
301// ----------------------------------------------------------------------------
302AI_FORCE_INLINE
303size_t IOSystem::StackSize() const {
304 return m_pathStack.size();
305}
306
307// ----------------------------------------------------------------------------
308AI_FORCE_INLINE
309bool IOSystem::PopDirectory() {
310 if ( m_pathStack.empty() ) {
311 return false;
312 }
313
314 m_pathStack.pop_back();
315
316 return true;
317}
318
319// ----------------------------------------------------------------------------
320AI_FORCE_INLINE
321bool IOSystem::CreateDirectory( const std::string &path ) {
322 if ( path.empty() ) {
323 return false;
324 }
325
326#ifdef _WIN32
327 return 0 != ::_mkdir( path.c_str() );
328#else
329 return 0 != ::mkdir( path.c_str(), 0777 );
330#endif // _WIN32
331}
332
333// ----------------------------------------------------------------------------
334AI_FORCE_INLINE
335bool IOSystem::ChangeDirectory( const std::string &path ) {
336 if ( path.empty() ) {
337 return false;
338 }
339
340#ifdef _WIN32
341 return 0 != ::_chdir( path.c_str() );
342#else
343 return 0 != ::chdir( path.c_str() );
344#endif // _WIN32
345}
346
347
348// ----------------------------------------------------------------------------
349AI_FORCE_INLINE
350bool IOSystem::DeleteFile( const std::string &file ) {
351 if ( file.empty() ) {
352 return false;
353 }
354 const int retCode( ::remove( file.c_str() ) );
355 return ( 0 == retCode );
356}
357} //!ns Assimp
358
359#endif //AI_IOSYSTEM_H_INC
360