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