Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/OgreMain/src/OgreZip.cpp @ 1

Last change on this file since 1 was 1, checked in by landauf, 17 years ago
File size: 11.2 KB
Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4(Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2006 Torus Knot Software Ltd
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23
24You may alternatively use this source under the terms of a specific version of
25the OGRE Unrestricted License provided you have obtained such a license from
26Torus Knot Software Ltd.
27-----------------------------------------------------------------------------
28*/
29#include "OgreStableHeaders.h"
30
31#include "OgreZip.h"
32
33#include "OgreLogManager.h"
34#include "OgreException.h"
35#include "OgreStringVector.h"
36#include "OgreRoot.h"
37
38#include <zzip/zzip.h>
39
40
41namespace Ogre {
42
43    /// Utility method to format out zzip errors
44    String getZzipErrorDescription(zzip_error_t zzipError) 
45    {
46        String errorMsg;
47        switch (zzipError)
48        {
49        case ZZIP_NO_ERROR:
50            break;
51        case ZZIP_OUTOFMEM:
52            errorMsg = "Out of memory.";
53            break;           
54        case ZZIP_DIR_OPEN:
55        case ZZIP_DIR_STAT: 
56        case ZZIP_DIR_SEEK:
57        case ZZIP_DIR_READ:
58            errorMsg = "Unable to read zip file.";
59            break;           
60        case ZZIP_UNSUPP_COMPR:
61            errorMsg = "Unsupported compression format.";
62            break;           
63        case ZZIP_CORRUPTED:
64            errorMsg = "Corrupted archive.";
65            break;           
66        default:
67            errorMsg = "Unknown error.";
68            break;           
69        };
70
71        return errorMsg;
72    }
73    //-----------------------------------------------------------------------
74    ZipArchive::ZipArchive(const String& name, const String& archType )
75        : Archive(name, archType), mZzipDir(0)
76    {
77    }
78    //-----------------------------------------------------------------------
79    ZipArchive::~ZipArchive()
80    {
81        unload();
82    }
83    //-----------------------------------------------------------------------
84    void ZipArchive::load()
85    {
86        if (!mZzipDir)
87        {
88            zzip_error_t zzipError;
89            mZzipDir = zzip_dir_open(mName.c_str(), &zzipError);
90            checkZzipError(zzipError, "opening archive");
91
92            // Cache names
93            ZZIP_DIRENT zzipEntry;
94            while (zzip_dir_read(mZzipDir, &zzipEntry))
95            {
96                FileInfo info;
97                                info.archive = this;
98                // Get basename / path
99                StringUtil::splitFilename(zzipEntry.d_name, info.basename, info.path);
100                info.filename = zzipEntry.d_name;
101                // Get sizes
102                info.compressedSize = static_cast<size_t>(zzipEntry.d_csize);
103                info.uncompressedSize = static_cast<size_t>(zzipEntry.st_size);
104                // folder entries
105                if (info.basename.empty())
106                {
107                    info.filename = info.filename.substr (0, info.filename.length () - 1);
108                    StringUtil::splitFilename(info.filename, info.basename, info.path);
109                    // Set compressed size to -1 for folders; anyway nobody will check
110                    // the compressed size of a folder, and if he does, its useless anyway
111                    info.compressedSize = size_t (-1);
112                }
113
114                mFileList.push_back(info);
115
116            }
117
118        }
119    }
120    //-----------------------------------------------------------------------
121    void ZipArchive::unload()
122    {
123        if (mZzipDir)
124        {
125            zzip_dir_close(mZzipDir);
126            mZzipDir = 0;
127            mFileList.clear();
128        }
129   
130    }
131    //-----------------------------------------------------------------------
132        DataStreamPtr ZipArchive::open(const String& filename) const
133    {
134
135        // Format not used here (always binary)
136        ZZIP_FILE* zzipFile = 
137            zzip_file_open(mZzipDir, filename.c_str(), ZZIP_ONLYZIP | ZZIP_CASELESS);
138        if (!zzipFile)
139                {
140            int zerr = zzip_error(mZzipDir);
141            String zzDesc = getZzipErrorDescription((zzip_error_t)zerr);
142            LogManager::getSingleton().logMessage(
143                mName + " - Unable to open file " + filename + ", error was '" + zzDesc + "'");
144               
145                        // return null pointer
146                        return DataStreamPtr();
147                }
148
149                // Get uncompressed size too
150                ZZIP_STAT zstat;
151                zzip_dir_stat(mZzipDir, filename.c_str(), &zstat, ZZIP_CASEINSENSITIVE);
152
153        // Construct & return stream
154        return DataStreamPtr(new ZipDataStream(filename, zzipFile, static_cast<size_t>(zstat.st_size)));
155
156    }
157    //-----------------------------------------------------------------------
158    StringVectorPtr ZipArchive::list(bool recursive, bool dirs)
159    {
160        StringVectorPtr ret = StringVectorPtr(new StringVector());
161
162        FileInfoList::iterator i, iend;
163        iend = mFileList.end();
164        for (i = mFileList.begin(); i != iend; ++i)
165            if ((dirs == (i->compressedSize == size_t (-1))) &&
166                (recursive || i->path.empty()))
167                ret->push_back(i->filename);
168
169        return ret;
170    }
171    //-----------------------------------------------------------------------
172    FileInfoListPtr ZipArchive::listFileInfo(bool recursive, bool dirs)
173    {
174        FileInfoList* fil = new FileInfoList();
175        FileInfoList::const_iterator i, iend;
176        iend = mFileList.end();
177        for (i = mFileList.begin(); i != iend; ++i)
178            if ((dirs == (i->compressedSize == size_t (-1))) &&
179                (recursive || i->path.empty()))
180                fil->push_back(*i);
181
182        return FileInfoListPtr(fil);
183    }
184    //-----------------------------------------------------------------------
185    StringVectorPtr ZipArchive::find(const String& pattern, bool recursive, bool dirs)
186    {
187        StringVectorPtr ret = StringVectorPtr(new StringVector());
188        // If pattern contains a directory name, do a full match
189        bool full_match = (pattern.find ('/') != String::npos) ||
190                          (pattern.find ('\\') != String::npos);
191
192        FileInfoList::iterator i, iend;
193        iend = mFileList.end();
194        for (i = mFileList.begin(); i != iend; ++i)
195            if ((dirs == (i->compressedSize == size_t (-1))) &&
196                (recursive || full_match || i->path.empty()))
197                // Check basename matches pattern (zip is case insensitive)
198                if (StringUtil::match(full_match ? i->filename : i->basename, pattern, false))
199                    ret->push_back(i->filename);
200
201        return ret;
202    }
203    //-----------------------------------------------------------------------
204        FileInfoListPtr ZipArchive::findFileInfo(const String& pattern, 
205        bool recursive, bool dirs)
206    {
207        FileInfoListPtr ret = FileInfoListPtr(new FileInfoList());
208        // If pattern contains a directory name, do a full match
209        bool full_match = (pattern.find ('/') != String::npos) ||
210                          (pattern.find ('\\') != String::npos);
211
212        FileInfoList::iterator i, iend;
213        iend = mFileList.end();
214        for (i = mFileList.begin(); i != iend; ++i)
215            if ((dirs == (i->compressedSize == size_t (-1))) &&
216                (recursive || full_match || i->path.empty()))
217                // Check name matches pattern (zip is case insensitive)
218                if (StringUtil::match(full_match ? i->filename : i->basename, pattern, false))
219                    ret->push_back(*i);
220
221        return ret;
222    }
223    //-----------------------------------------------------------------------
224        bool ZipArchive::exists(const String& filename)
225        {
226                ZZIP_STAT zstat;
227                int res = zzip_dir_stat(mZzipDir, filename.c_str(), &zstat, ZZIP_CASEINSENSITIVE);
228
229                return (res == ZZIP_NO_ERROR);
230
231        }
232        //-----------------------------------------------------------------------
233    void ZipArchive::checkZzipError(int zzipError, const String& operation) const
234    {
235        if (zzipError != ZZIP_NO_ERROR)
236        {
237            String errorMsg = getZzipErrorDescription(static_cast<zzip_error_t>(zzipError));
238
239            OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, 
240                mName + " - error whilst " + operation + ": " + errorMsg,
241                "ZipArchive::checkZzipError");
242        }
243    }
244    //-----------------------------------------------------------------------
245    //-----------------------------------------------------------------------
246    //-----------------------------------------------------------------------
247    ZipDataStream::ZipDataStream(ZZIP_FILE* zzipFile, size_t uncompressedSize)
248        : mZzipFile(zzipFile)
249    {
250                mSize = uncompressedSize;
251    }
252    //-----------------------------------------------------------------------
253    ZipDataStream::ZipDataStream(const String& name, ZZIP_FILE* zzipFile, size_t uncompressedSize)
254        :DataStream(name), mZzipFile(zzipFile)
255    {
256                mSize = uncompressedSize;
257    }
258    //-----------------------------------------------------------------------
259        ZipDataStream::~ZipDataStream()
260        {
261                close();
262        }
263    //-----------------------------------------------------------------------
264    size_t ZipDataStream::read(void* buf, size_t count)
265    {
266        return zzip_file_read(mZzipFile, (char*)buf, count);
267    }
268    //-----------------------------------------------------------------------
269    void ZipDataStream::skip(long count)
270    {
271        zzip_seek(mZzipFile, static_cast<zzip_off_t>(count), SEEK_CUR);
272    }
273    //-----------------------------------------------------------------------
274    void ZipDataStream::seek( size_t pos )
275    {
276                zzip_seek(mZzipFile, static_cast<zzip_off_t>(pos), SEEK_SET);
277    }
278    //-----------------------------------------------------------------------
279    size_t ZipDataStream::tell(void) const
280    {
281                return zzip_tell(mZzipFile);
282    }
283    //-----------------------------------------------------------------------
284    bool ZipDataStream::eof(void) const
285    {
286        return (zzip_tell(mZzipFile) >= static_cast<zzip_off_t>(mSize));
287    }
288    //-----------------------------------------------------------------------
289    void ZipDataStream::close(void)
290    {
291        zzip_file_close(mZzipFile);
292    }
293    //-----------------------------------------------------------------------
294    const String& ZipArchiveFactory::getType(void) const
295    {
296        static String name = "Zip";
297        return name;
298    }
299
300}
Note: See TracBrowser for help on using the repository browser.