Coverage Report

Created: 2025-08-26 06:41

/src/assimp/code/Common/ZipArchiveIOSystem.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
Open Asset Import Library (assimp)
3
----------------------------------------------------------------------
4
5
Copyright (c) 2006-2025, assimp team
6
7
All rights reserved.
8
9
Redistribution and use of this software in source and binary forms,
10
with or without modification, are permitted provided that the
11
following conditions are met:
12
13
* Redistributions of source code must retain the above
14
  copyright notice, this list of conditions and the
15
  following disclaimer.
16
17
* Redistributions in binary form must reproduce the above
18
  copyright notice, this list of conditions and the
19
  following disclaimer in the documentation and/or other
20
  materials provided with the distribution.
21
22
* Neither the name of the assimp team, nor the names of its
23
  contributors may be used to endorse or promote products
24
  derived from this software without specific prior
25
  written permission of the assimp team.
26
27
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
32
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
33
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38
39
----------------------------------------------------------------------
40
*/
41
42
/** @file  ZipArchiveIOSystem.cpp
43
 *  @brief Zip File I/O implementation for #Importer
44
 */
45
46
#include <assimp/BaseImporter.h>
47
#include <assimp/ZipArchiveIOSystem.h>
48
49
#include <assimp/ai_assert.h>
50
51
#include <map>
52
#include <memory>
53
54
#ifdef ASSIMP_USE_HUNTER
55
#    include <minizip/unzip.h>
56
#else
57
#    include <unzip.h>
58
#endif
59
60
namespace Assimp {
61
62
// ----------------------------------------------------------------
63
// A read-only file inside a ZIP
64
65
class ZipFile final : public IOStream {
66
    friend class ZipFileInfo;
67
    explicit ZipFile(std::string &filename, size_t size);
68
69
public:
70
    std::string m_Filename;
71
0
    ~ZipFile() override = default;
72
73
    // IOStream interface
74
    size_t Read(void *pvBuffer, size_t pSize, size_t pCount) override;
75
0
    size_t Write(const void * /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/) override { return 0; }
76
    size_t FileSize() const override;
77
    aiReturn Seek(size_t pOffset, aiOrigin pOrigin) override;
78
    size_t Tell() const override;
79
0
    void Flush() override {}
80
81
private:
82
    size_t m_Size = 0;
83
    size_t m_SeekPtr = 0;
84
    std::unique_ptr<uint8_t[]> m_Buffer;
85
};
86
87
88
// ----------------------------------------------------------------
89
// Wraps an existing Assimp::IOSystem for unzip
90
class IOSystem2Unzip {
91
public:
92
    IOSystem2Unzip() = default;
93
    ~IOSystem2Unzip() = default;
94
    static voidpf open(voidpf opaque, const char *filename, int mode);
95
    static voidpf opendisk(voidpf opaque, voidpf stream, uint32_t number_disk, int mode);
96
    static uLong read(voidpf opaque, voidpf stream, void *buf, uLong size);
97
    static uLong write(voidpf opaque, voidpf stream, const void *buf, uLong size);
98
    static long tell(voidpf opaque, voidpf stream);
99
    static long seek(voidpf opaque, voidpf stream, uLong offset, int origin);
100
    static int close(voidpf opaque, voidpf stream);
101
    static int testerror(voidpf opaque, voidpf stream);
102
    static zlib_filefunc_def get(IOSystem *pIOHandler);
103
};
104
105
// ----------------------------------------------------------------
106
159
voidpf IOSystem2Unzip::open(voidpf opaque, const char *filename, int mode) {
107
159
    IOSystem *io_system = reinterpret_cast<IOSystem *>(opaque);
108
109
159
    const char *mode_fopen = nullptr;
110
159
    if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER) == ZLIB_FILEFUNC_MODE_READ) {
111
159
        mode_fopen = "rb";
112
159
    } else {
113
0
        if (mode & ZLIB_FILEFUNC_MODE_EXISTING) {
114
0
            mode_fopen = "r+b";
115
0
        } else {
116
0
            if (mode & ZLIB_FILEFUNC_MODE_CREATE) {
117
0
                mode_fopen = "wb";
118
0
            }
119
0
        }
120
0
    }
121
122
159
    return (voidpf)io_system->Open(filename, mode_fopen);
123
159
}
124
125
// ----------------------------------------------------------------
126
0
voidpf IOSystem2Unzip::opendisk(voidpf opaque, voidpf stream, uint32_t number_disk, int mode) {
127
0
    ZipFile *io_stream = (ZipFile *)stream;
128
0
    voidpf ret = nullptr;
129
0
    int i;
130
131
0
    char *disk_filename = (char*)malloc(io_stream->m_Filename.length() + 1);
132
0
    strncpy(disk_filename, io_stream->m_Filename.c_str(), io_stream->m_Filename.length() + 1);
133
0
    for (i = (int)io_stream->m_Filename.length() - 1; i >= 0; i -= 1)
134
0
    {
135
0
        if (disk_filename[i] != '.')
136
0
            continue;
137
0
        snprintf(&disk_filename[i], io_stream->m_Filename.length() - size_t(i), ".z%02u", number_disk + 1);
138
0
        break;
139
0
    }
140
141
0
    if (i >= 0)
142
0
        ret = open(opaque, disk_filename, mode);
143
144
0
    free(disk_filename);
145
0
    return ret;
146
0
}
147
148
// ----------------------------------------------------------------
149
29.1k
uLong IOSystem2Unzip::read(voidpf /*opaque*/, voidpf stream, void *buf, uLong size) {
150
29.1k
    IOStream *io_stream = (IOStream *)stream;
151
152
29.1k
    return static_cast<uLong>(io_stream->Read(buf, 1, size));
153
29.1k
}
154
155
// ----------------------------------------------------------------
156
0
uLong IOSystem2Unzip::write(voidpf /*opaque*/, voidpf stream, const void *buf, uLong size) {
157
0
    IOStream *io_stream = (IOStream *)stream;
158
159
0
    return static_cast<uLong>(io_stream->Write(buf, 1, size));
160
0
}
161
162
// ----------------------------------------------------------------
163
318
long IOSystem2Unzip::tell(voidpf /*opaque*/, voidpf stream) {
164
318
    IOStream *io_stream = (IOStream *)stream;
165
166
318
    return static_cast<long>(io_stream->Tell());
167
318
}
168
169
// ----------------------------------------------------------------
170
16.1k
long IOSystem2Unzip::seek(voidpf /*opaque*/, voidpf stream, uLong offset, int origin) {
171
16.1k
    IOStream *io_stream = (IOStream *)stream;
172
173
16.1k
    aiOrigin assimp_origin;
174
16.1k
    switch (origin) {
175
0
        default:
176
160
        case ZLIB_FILEFUNC_SEEK_CUR:
177
160
            assimp_origin = aiOrigin_CUR;
178
160
            break;
179
318
        case ZLIB_FILEFUNC_SEEK_END:
180
318
            assimp_origin = aiOrigin_END;
181
318
            break;
182
15.7k
        case ZLIB_FILEFUNC_SEEK_SET:
183
15.7k
            assimp_origin = aiOrigin_SET;
184
15.7k
            break;
185
16.1k
    }
186
187
16.1k
    return (io_stream->Seek(offset, assimp_origin) == aiReturn_SUCCESS ? 0 : -1);
188
16.1k
}
189
190
// ----------------------------------------------------------------
191
159
int IOSystem2Unzip::close(voidpf opaque, voidpf stream) {
192
159
    IOSystem *io_system = (IOSystem *)opaque;
193
159
    IOStream *io_stream = (IOStream *)stream;
194
195
159
    io_system->Close(io_stream);
196
197
159
    return 0;
198
159
}
199
200
// ----------------------------------------------------------------
201
12
int IOSystem2Unzip::testerror(voidpf /*opaque*/, voidpf /*stream*/) {
202
12
    return 0;
203
12
}
204
205
// ----------------------------------------------------------------
206
159
zlib_filefunc_def IOSystem2Unzip::get(IOSystem *pIOHandler) {
207
159
    zlib_filefunc_def mapping;
208
209
159
    mapping.zopen_file = (open_file_func)open;
210
#ifdef _UNZ_H
211
    mapping.zopendisk_file = (opendisk_file_func)opendisk;
212
#endif
213
159
    mapping.zread_file = (read_file_func)read;
214
159
    mapping.zwrite_file = (write_file_func)write;
215
159
    mapping.ztell_file = (tell_file_func)tell;
216
159
    mapping.zseek_file = (seek_file_func)seek;
217
159
    mapping.zclose_file = (close_file_func)close;
218
159
    mapping.zerror_file = testerror;
219
220
159
    mapping.opaque = reinterpret_cast<voidpf>(pIOHandler);
221
222
159
    return mapping;
223
159
}
224
225
// ----------------------------------------------------------------
226
// Info about a read-only file inside a ZIP
227
class ZipFileInfo final {
228
public:
229
    explicit ZipFileInfo(unzFile zip_handle, size_t size);
230
    ~ZipFileInfo() = default;
231
232
    // Allocate and Extract data from the ZIP
233
    ZipFile *Extract(std::string &filename, unzFile zip_handle) const;
234
235
private:
236
    size_t m_Size = 0;
237
    unz_file_pos_s m_ZipFilePos;
238
};
239
240
// ----------------------------------------------------------------
241
ZipFileInfo::ZipFileInfo(unzFile zip_handle, size_t size) :
242
365
        m_Size(size) {
243
365
    ai_assert(m_Size != 0);
244
    // Workaround for MSVC 2013 - C2797
245
365
    m_ZipFilePos.num_of_file = 0;
246
365
    m_ZipFilePos.pos_in_zip_directory = 0;
247
365
    unzGetFilePos(zip_handle, &(m_ZipFilePos));
248
365
}
249
250
// ----------------------------------------------------------------
251
0
ZipFile *ZipFileInfo::Extract(std::string &filename, unzFile zip_handle) const {
252
    // Find in the ZIP. This cannot fail
253
0
    unz_file_pos_s *filepos = const_cast<unz_file_pos_s *>(&(m_ZipFilePos));
254
0
    if (unzGoToFilePos(zip_handle, filepos) != UNZ_OK)
255
0
        return nullptr;
256
257
0
    if (unzOpenCurrentFile(zip_handle) != UNZ_OK)
258
0
        return nullptr;
259
260
0
    ZipFile *zip_file = new ZipFile(filename, m_Size);
261
262
    // Unzip has a limit of UINT16_MAX bytes buffer
263
0
    uint16_t unzipBufferSize = zip_file->m_Size <= UINT16_MAX ? static_cast<uint16_t>(zip_file->m_Size) : UINT16_MAX;
264
0
    std::unique_ptr<uint8_t[]> unzipBuffer = std::unique_ptr<uint8_t[]>(new uint8_t[unzipBufferSize]);
265
0
    size_t readCount = 0;
266
0
    while (readCount < zip_file->m_Size)
267
0
    {
268
0
        size_t bufferSize = zip_file->m_Size - readCount;
269
0
        if (bufferSize > UINT16_MAX) {
270
0
            bufferSize = UINT16_MAX;
271
0
        }
272
273
0
        int ret = unzReadCurrentFile(zip_handle, unzipBuffer.get(), static_cast<unsigned int>(bufferSize));
274
0
        if (ret != static_cast<int>(bufferSize))
275
0
        {
276
            // Failed, release the memory
277
0
            delete zip_file;
278
0
            zip_file = nullptr;
279
0
            break;
280
0
        }
281
282
0
        std::memcpy(zip_file->m_Buffer.get() + readCount, unzipBuffer.get(), ret);
283
0
        readCount += ret;
284
0
    }
285
286
0
    ai_assert(unzCloseCurrentFile(zip_handle) == UNZ_OK);
287
0
    return zip_file;
288
0
}
289
290
// ----------------------------------------------------------------
291
ZipFile::ZipFile(std::string &filename, size_t size) :
292
0
        m_Filename(filename), m_Size(size) {
293
0
    ai_assert(m_Size != 0);
294
0
    m_Buffer = std::unique_ptr<uint8_t[]>(new uint8_t[m_Size]);
295
0
}
296
297
// ----------------------------------------------------------------
298
0
size_t ZipFile::Read(void *pvBuffer, size_t pSize, size_t pCount) {
299
    // Should be impossible
300
0
    ai_assert(m_Buffer != nullptr);
301
0
    ai_assert(nullptr != pvBuffer);
302
0
    ai_assert(0 != pSize);
303
0
    ai_assert(0 != pCount);
304
305
    // Clip down to file size
306
0
    size_t byteSize = pSize * pCount;
307
0
    if ((byteSize + m_SeekPtr) > m_Size) {
308
0
        pCount = (m_Size - m_SeekPtr) / pSize;
309
0
        byteSize = pSize * pCount;
310
0
        if (byteSize == 0) {
311
0
            return 0;
312
0
        }
313
0
    }
314
315
0
    std::memcpy(pvBuffer, m_Buffer.get() + m_SeekPtr, byteSize);
316
317
0
    m_SeekPtr += byteSize;
318
319
0
    return pCount;
320
0
}
321
322
// ----------------------------------------------------------------
323
0
size_t ZipFile::FileSize() const {
324
0
    return m_Size;
325
0
}
326
327
// ----------------------------------------------------------------
328
0
aiReturn ZipFile::Seek(size_t pOffset, aiOrigin pOrigin) {
329
0
    switch (pOrigin) {
330
0
        case aiOrigin_SET: {
331
0
            if (pOffset > m_Size) return aiReturn_FAILURE;
332
0
            m_SeekPtr = pOffset;
333
0
            return aiReturn_SUCCESS;
334
0
        }
335
336
0
        case aiOrigin_CUR: {
337
0
            if ((pOffset + m_SeekPtr) > m_Size) return aiReturn_FAILURE;
338
0
            m_SeekPtr += pOffset;
339
0
            return aiReturn_SUCCESS;
340
0
        }
341
342
0
        case aiOrigin_END: {
343
0
            if (pOffset > m_Size) return aiReturn_FAILURE;
344
0
            m_SeekPtr = m_Size - pOffset;
345
0
            return aiReturn_SUCCESS;
346
0
        }
347
0
        default:;
348
0
    }
349
350
0
    return aiReturn_FAILURE;
351
0
}
352
353
// ----------------------------------------------------------------
354
0
size_t ZipFile::Tell() const {
355
0
    return m_SeekPtr;
356
0
}
357
358
// ----------------------------------------------------------------
359
// pImpl of the Zip Archive IO
360
class ZipArchiveIOSystem::Implement {
361
public:
362
    static const unsigned int FileNameSize = 256;
363
364
    Implement(IOSystem *pIOHandler, const char *pFilename, const char *pMode);
365
    ~Implement();
366
367
    bool isOpen() const;
368
    void getFileList(std::vector<std::string> &rFileList);
369
    void getFileListExtension(std::vector<std::string> &rFileList, const std::string &extension);
370
    bool Exists(std::string &filename);
371
    IOStream *OpenFile(std::string &filename);
372
373
    static void SimplifyFilename(std::string &filename);
374
375
private:
376
    void MapArchive();
377
378
private:
379
    typedef std::map<std::string, ZipFileInfo> ZipFileInfoMap;
380
381
    unzFile m_ZipFileHandle = nullptr;
382
    ZipFileInfoMap m_ArchiveMap;
383
};
384
385
// ----------------------------------------------------------------
386
159
ZipArchiveIOSystem::Implement::Implement(IOSystem *pIOHandler, const char *pFilename, const char *pMode) {
387
159
    ai_assert(strcmp(pMode, "r") == 0);
388
159
    ai_assert(pFilename != nullptr);
389
159
    if (pFilename[0] == 0 || nullptr == pMode) {
390
0
        return;
391
0
    }
392
393
159
    zlib_filefunc_def mapping = IOSystem2Unzip::get(pIOHandler);
394
159
    m_ZipFileHandle = unzOpen2(pFilename, &mapping);
395
159
}
396
397
// ----------------------------------------------------------------
398
159
ZipArchiveIOSystem::Implement::~Implement() {
399
159
    if (m_ZipFileHandle != nullptr) {
400
33
        unzClose(m_ZipFileHandle);
401
33
    }
402
159
}
403
404
// ----------------------------------------------------------------
405
36
void ZipArchiveIOSystem::Implement::MapArchive() {
406
36
    if (m_ZipFileHandle == nullptr)
407
0
        return;
408
409
36
    if (!m_ArchiveMap.empty())
410
12
        return;
411
412
    //  At first ensure file is already open
413
24
    if (unzGoToFirstFile(m_ZipFileHandle) != UNZ_OK)
414
0
        return;
415
416
    // Loop over all files
417
374
    do {
418
374
        char filename[FileNameSize];
419
374
        unz_file_info fileInfo;
420
421
374
        if (unzGetCurrentFileInfo(m_ZipFileHandle, &fileInfo, filename, FileNameSize, nullptr, 0, nullptr, 0) == UNZ_OK) {
422
368
            if (fileInfo.uncompressed_size != 0 && fileInfo.size_filename <= FileNameSize) {
423
365
                std::string filename_string(filename, fileInfo.size_filename);
424
365
                SimplifyFilename(filename_string);
425
365
                m_ArchiveMap.emplace(filename_string, ZipFileInfo(m_ZipFileHandle, fileInfo.uncompressed_size));
426
365
            }
427
368
        }
428
374
    } while (unzGoToNextFile(m_ZipFileHandle) != UNZ_END_OF_LIST_OF_FILE);
429
24
}
430
431
// ----------------------------------------------------------------
432
149
bool ZipArchiveIOSystem::Implement::isOpen() const {
433
149
    return (m_ZipFileHandle != nullptr);
434
149
}
435
436
// ----------------------------------------------------------------
437
0
void ZipArchiveIOSystem::Implement::getFileList(std::vector<std::string> &rFileList) {
438
0
    MapArchive();
439
0
    rFileList.clear();
440
441
0
    for (const auto &file : m_ArchiveMap) {
442
0
        rFileList.push_back(file.first);
443
0
    }
444
0
}
445
446
// ----------------------------------------------------------------
447
13
void ZipArchiveIOSystem::Implement::getFileListExtension(std::vector<std::string> &rFileList, const std::string &extension) {
448
13
    MapArchive();
449
13
    rFileList.clear();
450
451
188
    for (const auto &file : m_ArchiveMap) {
452
188
        if (extension == BaseImporter::GetExtension(file.first))
453
0
            rFileList.push_back(file.first);
454
188
    }
455
13
}
456
457
// ----------------------------------------------------------------
458
10
bool ZipArchiveIOSystem::Implement::Exists(std::string &filename) {
459
10
    MapArchive();
460
461
10
    ZipFileInfoMap::const_iterator it = m_ArchiveMap.find(filename);
462
10
    return (it != m_ArchiveMap.end());
463
10
}
464
465
// ----------------------------------------------------------------
466
13
IOStream *ZipArchiveIOSystem::Implement::OpenFile(std::string &filename) {
467
13
    MapArchive();
468
469
13
    SimplifyFilename(filename);
470
471
    // Find in the map
472
13
    ZipFileInfoMap::const_iterator zip_it = m_ArchiveMap.find(filename);
473
13
    if (zip_it == m_ArchiveMap.cend())
474
13
        return nullptr;
475
476
0
    const ZipFileInfo &zip_file = (*zip_it).second;
477
0
    return zip_file.Extract(filename, m_ZipFileHandle);
478
13
}
479
480
// ----------------------------------------------------------------
481
0
inline void ReplaceAll(std::string &data, const std::string &before, const std::string &after) {
482
0
    size_t pos = data.find(before);
483
0
    while (pos != std::string::npos) {
484
0
        data.replace(pos, before.size(), after);
485
0
        pos = data.find(before, pos + after.size());
486
0
    }
487
0
}
488
489
// ----------------------------------------------------------------
490
378
inline void ReplaceAllChar(std::string &data, const char before, const char after) {
491
378
    size_t pos = data.find(before);
492
378
    while (pos != std::string::npos) {
493
0
        data[pos] = after;
494
0
        pos = data.find(before, pos + 1);
495
0
    }
496
378
}
497
498
// ----------------------------------------------------------------
499
378
void ZipArchiveIOSystem::Implement::SimplifyFilename(std::string &filename) {
500
378
    ReplaceAllChar(filename, '\\', '/');
501
502
    // Remove all . and / from the beginning of the path
503
378
    size_t pos = filename.find_first_not_of("./");
504
378
    if (pos != 0)
505
1
        filename.erase(0, pos);
506
507
    // Simplify "my/folder/../file.png" constructions, if any
508
378
    static const std::string relative("/../");
509
378
    const size_t relsize = relative.size() - 1;
510
378
    pos = filename.find(relative);
511
378
    while (pos != std::string::npos) {
512
        // Previous slash
513
0
        size_t prevpos = filename.rfind('/', pos - 1);
514
0
        if (prevpos == pos)
515
0
            filename.erase(0, pos + relative.size());
516
0
        else
517
0
            filename.erase(prevpos, pos + relsize - prevpos);
518
519
0
        pos = filename.find(relative);
520
0
    }
521
378
}
522
523
// ----------------------------------------------------------------
524
ZipArchiveIOSystem::ZipArchiveIOSystem(IOSystem *pIOHandler, const char *pFilename, const char *pMode) :
525
0
        pImpl(new Implement(pIOHandler, pFilename, pMode)) {
526
0
}
527
528
// ----------------------------------------------------------------
529
// The ZipArchiveIO
530
ZipArchiveIOSystem::ZipArchiveIOSystem(IOSystem *pIOHandler, const std::string &rFilename, const char *pMode) :
531
122
        pImpl(new Implement(pIOHandler, rFilename.c_str(), pMode)) {
532
122
}
533
534
// ----------------------------------------------------------------
535
122
ZipArchiveIOSystem::~ZipArchiveIOSystem() {
536
122
    delete pImpl;
537
122
}
538
539
// ----------------------------------------------------------------
540
10
bool ZipArchiveIOSystem::Exists(const char *pFilename) const {
541
10
    ai_assert(pFilename != nullptr);
542
543
10
    if (pFilename == nullptr) {
544
0
        return false;
545
0
    }
546
547
10
    std::string filename(pFilename);
548
10
    return pImpl->Exists(filename);
549
10
}
550
551
// ----------------------------------------------------------------
552
// This is always '/' in a ZIP
553
0
char ZipArchiveIOSystem::getOsSeparator() const {
554
0
    return '/';
555
0
}
556
557
// ----------------------------------------------------------------
558
// Only supports Reading
559
13
IOStream *ZipArchiveIOSystem::Open(const char *pFilename, const char *pMode) {
560
13
    ai_assert(pFilename != nullptr);
561
562
39
    for (size_t i = 0; pMode[i] != 0; ++i) {
563
26
        ai_assert(pMode[i] != 'w');
564
26
        if (pMode[i] == 'w')
565
0
            return nullptr;
566
26
    }
567
568
13
    std::string filename(pFilename);
569
13
    return pImpl->OpenFile(filename);
570
13
}
571
572
// ----------------------------------------------------------------
573
0
void ZipArchiveIOSystem::Close(IOStream *pFile) {
574
0
    delete pFile;
575
0
}
576
577
// ----------------------------------------------------------------
578
112
bool ZipArchiveIOSystem::isOpen() const {
579
112
    return (pImpl->isOpen());
580
112
}
581
582
// ----------------------------------------------------------------
583
0
void ZipArchiveIOSystem::getFileList(std::vector<std::string> &rFileList) const {
584
0
    return pImpl->getFileList(rFileList);
585
0
}
586
587
// ----------------------------------------------------------------
588
13
void ZipArchiveIOSystem::getFileListExtension(std::vector<std::string> &rFileList, const std::string &extension) const {
589
13
    return pImpl->getFileListExtension(rFileList, extension);
590
13
}
591
592
// ----------------------------------------------------------------
593
37
bool ZipArchiveIOSystem::isZipArchive(IOSystem *pIOHandler, const char *pFilename) {
594
37
    Implement tmp(pIOHandler, pFilename, "r");
595
37
    return tmp.isOpen();
596
37
}
597
598
37
bool ZipArchiveIOSystem::isZipArchive(IOSystem *pIOHandler, const std::string &rFilename) {
599
37
    return isZipArchive(pIOHandler, rFilename.c_str());
600
37
}
601
602
} // namespace Assimp