source: OGRE/trunk/ogrenew/OgreMain/src/OgreZip.cpp @ 657

Revision 657, 12.4 KB checked in by mattausch, 18 years ago (diff)

added ogre dependencies and patched ogre sources

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-2005 The OGRE Team
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-----------------------------------------------------------------------------
24*/
25#include "OgreStableHeaders.h"
26
27#include "OgreZip.h"
28
29#include "OgreLogManager.h"
30#include "OgreException.h"
31#include "OgreStringVector.h"
32#include "OgreRoot.h"
33
34#include <zzip/zzip.h>
35
36
37namespace Ogre {
38
39    /// Utility method to format out zzip errors
40    String getZzipErrorDescription(zzip_error_t zzipError)
41    {
42        String errorMsg;
43        switch (zzipError)
44        {
45        case ZZIP_NO_ERROR:
46            break;
47        case ZZIP_OUTOFMEM:
48            errorMsg = "Out of memory.";
49            break;           
50        case ZZIP_DIR_OPEN:
51        case ZZIP_DIR_STAT:
52        case ZZIP_DIR_SEEK:
53        case ZZIP_DIR_READ:
54            errorMsg = "Unable to read zip file.";
55            break;           
56        case ZZIP_UNSUPP_COMPR:
57            errorMsg = "Unsupported compression format.";
58            break;           
59        case ZZIP_CORRUPTED:
60            errorMsg = "Corrupted archive.";
61            break;           
62        default:
63            errorMsg = "Unknown error.";
64            break;           
65        };
66
67        return errorMsg;
68    }
69    //-----------------------------------------------------------------------
70    ZipArchive::ZipArchive(const String& name, const String& archType )
71        : Archive(name, archType), mZzipDir(0)
72    {
73    }
74    //-----------------------------------------------------------------------
75    ZipArchive::~ZipArchive()
76    {
77        unload();
78    }
79    //-----------------------------------------------------------------------
80    void ZipArchive::load()
81    {
82        if (!mZzipDir)
83        {
84            zzip_error_t zzipError;
85            mZzipDir = zzip_dir_open(mName.c_str(), &zzipError);
86            checkZzipError(zzipError, "opening archive");
87
88            // Cache names
89            ZZIP_DIRENT zzipEntry;
90            while (zzip_dir_read(mZzipDir, &zzipEntry))
91            {
92                FileInfo info;
93                                info.archive = this;
94                // Get basename / path
95                StringUtil::splitFilename(zzipEntry.d_name, info.basename, info.path);
96                // ignore folder entries
97                if (info.basename.empty())
98                    continue;
99                info.filename = zzipEntry.d_name;
100                // Get sizes
101                info.compressedSize = static_cast<size_t>(zzipEntry.d_csize);
102                info.uncompressedSize = static_cast<size_t>(zzipEntry.st_size);
103
104                mFileList.push_back(info);
105
106            }
107
108        }
109    }
110    //-----------------------------------------------------------------------
111    void ZipArchive::unload()
112    {
113        if (mZzipDir)
114        {
115            zzip_dir_close(mZzipDir);
116            mZzipDir = 0;
117            mFileList.clear();
118        }
119   
120    }
121    //-----------------------------------------------------------------------
122        DataStreamPtr ZipArchive::open(const String& filename) const
123    {
124
125        // Format not used here (always binary)
126        ZZIP_FILE* zzipFile =
127            zzip_file_open(mZzipDir, filename.c_str(), ZZIP_ONLYZIP | ZZIP_CASELESS);
128        if (!zzipFile)
129                {
130            int zerr = zzip_error(mZzipDir);
131            String zzDesc = getZzipErrorDescription((zzip_error_t)zerr);
132            LogManager::getSingleton().logMessage(
133                mName + " - Unable to open file " + filename + ", error was '" + zzDesc + "'");
134               
135                        // return null pointer
136                        return DataStreamPtr();
137                }
138
139                // Get uncompressed size too
140                ZZIP_STAT zstat;
141                zzip_dir_stat(mZzipDir, filename.c_str(), &zstat, ZZIP_CASEINSENSITIVE);
142
143        // Construct & return stream
144        return DataStreamPtr(new ZipDataStream(filename, zzipFile, static_cast<size_t>(zstat.st_size)));
145
146    }
147    //-----------------------------------------------------------------------
148    StringVectorPtr ZipArchive::list(bool recursive)
149    {
150        StringVectorPtr ret = StringVectorPtr(new StringVector());
151
152        FileInfoList::iterator i, iend;
153        iend = mFileList.end();
154        for (i = mFileList.begin(); i != iend; ++i)
155        {
156                        if (recursive || i->path.empty())
157            {
158                ret->push_back(i->filename);
159            }
160        }
161        return ret;
162
163    }
164    //-----------------------------------------------------------------------
165    FileInfoListPtr ZipArchive::listFileInfo(bool recursive)
166    {
167        FileInfoList* fil = new FileInfoList();
168        FileInfoList::const_iterator i, iend;
169        iend = mFileList.end();
170        for (i = mFileList.begin(); i != iend; ++i)
171        {
172            if (recursive || i->path.empty())
173            {
174                fil->push_back(*i);
175            }
176        }
177        return FileInfoListPtr(fil);
178    }
179    //-----------------------------------------------------------------------
180    StringVectorPtr ZipArchive::find(const String& pattern, bool recursive)
181    {
182        StringVectorPtr ret = StringVectorPtr(new StringVector());
183
184        FileInfoList::iterator i, iend;
185        iend = mFileList.end();
186        for (i = mFileList.begin(); i != iend; ++i)
187        {
188                        if (recursive || i->path.empty())
189            {
190                // Check basename matches pattern (zip is case insensitive)
191                if (StringUtil::match(i->basename, pattern, false))
192                {
193                    ret->push_back(i->filename);
194                }
195            }
196            else
197            {
198                // Check full name
199                if (StringUtil::match(i->filename, pattern, false))
200                {
201                    ret->push_back(i->filename);
202                }
203
204            }
205        }
206        return ret;
207    }
208    //-----------------------------------------------------------------------
209        FileInfoListPtr ZipArchive::findFileInfo(const String& pattern,
210        bool recursive)
211    {
212        FileInfoListPtr ret = FileInfoListPtr(new FileInfoList());
213
214        FileInfoList::iterator i, iend;
215        iend = mFileList.end();
216        for (i = mFileList.begin(); i != iend; ++i)
217        {
218            if (recursive || i->path.empty())
219            {
220                // Check name matches pattern (zip is case insensitive)
221                if (StringUtil::match(i->basename, pattern, false))
222                {
223                    ret->push_back(*i);
224                }
225            }
226            else
227            {
228                // Check full name
229                if (StringUtil::match(i->filename, pattern, false))
230                {
231                    ret->push_back(*i);
232                }
233
234            }
235        }
236        return ret;
237    }
238    //-----------------------------------------------------------------------
239        bool ZipArchive::exists(const String& filename)
240        {
241                ZZIP_STAT zstat;
242                int res = zzip_dir_stat(mZzipDir, filename.c_str(), &zstat, ZZIP_CASEINSENSITIVE);
243
244                return (res == ZZIP_NO_ERROR);
245
246        }
247        //-----------------------------------------------------------------------
248    void ZipArchive::checkZzipError(int zzipError, const String& operation) const
249    {
250        if (zzipError != ZZIP_NO_ERROR)
251        {
252            String errorMsg = getZzipErrorDescription(static_cast<zzip_error_t>(zzipError));
253
254            OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR,
255                mName + " - error whilst " + operation + ": " + errorMsg,
256                "ZipArchive::checkZzipError");
257        }
258    }
259    //-----------------------------------------------------------------------
260    //-----------------------------------------------------------------------
261    //-----------------------------------------------------------------------
262    ZipDataStream::ZipDataStream(ZZIP_FILE* zzipFile, size_t uncompressedSize)
263        : mZzipFile(zzipFile)
264    {
265                mSize = uncompressedSize;
266    }
267    //-----------------------------------------------------------------------
268    ZipDataStream::ZipDataStream(const String& name, ZZIP_FILE* zzipFile, size_t uncompressedSize)
269        :DataStream(name), mZzipFile(zzipFile)
270    {
271                mSize = uncompressedSize;
272    }
273    //-----------------------------------------------------------------------
274        ZipDataStream::~ZipDataStream()
275        {
276                close();
277        }
278    //-----------------------------------------------------------------------
279    size_t ZipDataStream::read(void* buf, size_t count)
280    {
281        return zzip_file_read(mZzipFile, (char*)buf, count);
282    }
283    //-----------------------------------------------------------------------
284    size_t ZipDataStream::readLine(char* buf, size_t maxCount, const String& delim)
285    {
286        // read in chunks
287                size_t chunkSize = std::min(maxCount, (size_t)OGRE_STREAM_TEMP_SIZE-1);
288                size_t totalCount = 0;
289                size_t readCount;
290                // Deal with both Unix & Windows LFs
291                bool trimCR = false;
292                if (delim.find_first_of('\n') != String::npos)
293                {
294                        trimCR = true;
295                }
296                while (chunkSize && (readCount = zzip_file_read(mZzipFile, mZipTmpArea, chunkSize)))
297                {
298                        // Terminate
299                        mZipTmpArea[readCount] = '\0';
300                        // Find first delimiter
301                        size_t pos = strcspn(mZipTmpArea, delim.c_str());
302
303                        if (pos < readCount)
304                        {
305                                // found terminator
306                // reposition backwards
307                zzip_off_t offset = static_cast<zzip_off_t>(pos) - static_cast<zzip_off_t>(readCount) + 1;
308                zzip_seek(mZzipFile, offset, SEEK_CUR);
309                        }
310
311                        if (pos > 0)
312                        {
313                                if (trimCR && mZipTmpArea[pos-1] == '\r')
314                                {
315                                        // strip off CR
316                                        --pos;
317                                }
318                                // Are we genuinely copying?
319                                if (buf)
320                                {
321                                        memcpy(buf, (const void*)mZipTmpArea, pos);
322                    buf[pos] = '\0';
323                                }
324                                totalCount += pos;
325                        }
326
327            if (pos < readCount)
328            {
329                // Found delimiter, break out
330                break;
331            }
332                        // Adjust chunkSize for next time
333                        chunkSize = std::min(maxCount-totalCount, (size_t)OGRE_STREAM_TEMP_SIZE-1);
334                       
335                }
336                return totalCount;
337    }
338    //-----------------------------------------------------------------------
339    size_t ZipDataStream::skipLine(const String& delim)
340    {
341                // Re-use readLine, but don't copy data
342                char* nullBuf = 0;
343        return readLine(nullBuf, 1024, delim);
344    }
345    //-----------------------------------------------------------------------
346    void ZipDataStream::skip(long count)
347    {
348        zzip_seek(mZzipFile, static_cast<zzip_off_t>(count), SEEK_CUR);
349    }
350    //-----------------------------------------------------------------------
351    void ZipDataStream::seek( size_t pos )
352    {
353                zzip_seek(mZzipFile, static_cast<zzip_off_t>(pos), SEEK_SET);
354    }
355    //-----------------------------------------------------------------------
356    size_t ZipDataStream::tell(void) const
357    {
358                return zzip_tell(mZzipFile);
359    }
360    //-----------------------------------------------------------------------
361    bool ZipDataStream::eof(void) const
362    {
363        return (zzip_tell(mZzipFile) >= static_cast<zzip_off_t>(mSize));
364    }
365    //-----------------------------------------------------------------------
366    void ZipDataStream::close(void)
367    {
368        zzip_file_close(mZzipFile);
369    }
370    //-----------------------------------------------------------------------
371    const String& ZipArchiveFactory::getType(void) const
372    {
373        static String name = "Zip";
374        return name;
375    }
376
377}
Note: See TracBrowser for help on using the repository browser.