| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370 |
- #include <string.h>
- #include <map>
- #include "../minizip/ioapi_mem.h"
- #include "core/ZipFileSystem.h"
- #include "core/Object.h"
- #include "utils/stringUtils.h"
- #include <algorithm>
- //#include "utils/utils.h"
- #ifdef __S3E__
- #include "s3eFile.h"
- #endif
- namespace oxygine
- {
- namespace file
- {
- bool sortFiles(const file_entry& ob1, const file_entry& ob2)
- {
- return strcmp_cns(ob1.name, ob2.name) < 0;
- }
- bool readEntry(const file_entry* entry, file::buffer& bf)
- {
- bf.data.clear();
- int r = unzGoToFilePos(entry->zp, const_cast<unz_file_pos*>(&entry->pos));
- OX_ASSERT(r == UNZ_OK);
- unz_file_info file_info;
- r = unzGetCurrentFileInfo(entry->zp, &file_info, 0, 0, 0, 0, 0, 0);
- OX_ASSERT(r == UNZ_OK);
- unzOpenCurrentFile(entry->zp);
- bf.data.resize(file_info.uncompressed_size);
- r = unzReadCurrentFile(entry->zp, &bf.data.front(), (int)bf.data.size());
- OX_ASSERT(r == (int)file_info.uncompressed_size);
- unzCloseCurrentFile(entry->zp);
- return true;
- }
- Zips::Zips(): _sort(false)
- {
- }
- Zips::~Zips()
- {
- reset();
- }
- void Zips::read(unzFile zp)
- {
- do
- {
- unz_file_pos pos;
- unzGetFilePos(zp, &pos);
- file_entry entry;
- unzGetCurrentFileInfo(zp, 0, entry.name, sizeof(entry.name) - 1, 0, 0, 0, 0);
- entry.pos = pos;
- entry.zp = zp;
- _files.push_back(entry);
- }
- while (unzGoToNextFile(zp) != UNZ_END_OF_LIST_OF_FILE);
- _sort = true;
- }
- void Zips::add(const unsigned char* data, unsigned int size)
- {
- zlib_filefunc_def ff;
- fill_memory_filefunc(&ff);
- zmemdata dta;
- dta.data = (char*)data;
- dta.size = size;
- unzFile zp = unzOpen2((const char*)&dta, &ff);
- OX_ASSERT(zp);
- if (!zp)
- return;
- zpitem item;
- item.handle = zp;
- _zps.push_back(item);
- read(zp);
- }
- void Zips::add(std::vector<char>& data)
- {
- zlib_filefunc_def ff;
- fill_memory_filefunc(&ff);
- zmemdata dta;
- dta.data = (char*)&data.front();
- dta.size = data.size();
- unzFile zp = unzOpen2((const char*)&dta, &ff);
- OX_ASSERT(zp);
- if (!zp)
- return;
- _zps.push_back(zpitem());
- zpitem& item = _zps.back();
- item.handle = zp;
- std::swap(item.data, data);
- read(zp);
- }
- voidpf ZCALLBACK ox_fopen(voidpf opaque, const char* filename, int mode)
- {
- return file::open(filename, "rb");
- }
- uLong ZCALLBACK ox_fread(voidpf opaque, voidpf stream, void* buf, uLong size)
- {
- return file::read((handle)stream, buf, (unsigned int)size);
- }
- /*
- uLong ZCALLBACK ox_fwriteOF(voidpf opaque, voidpf stream, const void* buf, uLong size)
- {
- }
- */
- long ZCALLBACK ox_ftell(voidpf opaque, voidpf stream)
- {
- return file::tell((handle)stream);
- }
- long ZCALLBACK ox_fseek(voidpf opaque, voidpf stream, uLong offset, int origin)
- {
- file::seek((handle)stream, (unsigned int)offset, origin);
- return 0;
- }
- int ZCALLBACK ox_fclose(voidpf opaque, voidpf stream)
- {
- file::close((handle)stream);
- return 0;
- }
- int ZCALLBACK ox_ferror(voidpf opaque, voidpf stream)
- {
- return 0;
- }
- void Zips::add(const char* name)
- {
- zlib_filefunc_def zpfs;
- memset(&zpfs, 0, sizeof(zpfs));
- zpfs.zopen_file = ox_fopen;
- zpfs.zread_file = ox_fread;
- zpfs.zwrite_file = 0;
- zpfs.ztell_file = ox_ftell;
- zpfs.zseek_file = ox_fseek;
- zpfs.zclose_file = ox_fclose;
- zpfs.zerror_file = ox_ferror;
- unzFile zp = unzOpen2(name, &zpfs);//todo, optimize search in zip
- OX_ASSERT(zp);
- if (!zp)
- return;
- zpitem item;
- item.handle = zp;
- strcpy(item.name, name);
- _zps.push_back(item);
- read(zp);
- }
- void Zips::update()
- {
- std::sort(_files.begin(), _files.end(), sortFiles);
- #ifdef OX_DEBUG
- for (size_t i = 0; i < _files.size() - 1; ++i)
- {
- OX_ASSERT(strcmp(_files[i].name, _files[i + 1].name) != 0);
- }
- #endif
- log::messageln("ZipFS, total files: %d", _files.size());
- }
- bool Zips::read(const char* name, file::buffer& bf)
- {
- const file_entry* entry = getEntryByName(name);
- if (!entry)
- return false;
- return readEntry(entry, bf);
- }
- bool Zips::read(const file_entry* entry, file::buffer& bf)
- {
- return readEntry(entry, bf);
- }
- void Zips::reset()
- {
- for (zips::iterator i = _zps.begin(); i != _zps.end(); ++i)
- {
- zpitem& f = *i;
- unzClose(f.handle);
- }
- _zps.clear();
- _files.clear();
- }
- bool findEntry(const file_entry& g, const char* name)
- {
- return strcmp_cns(g.name, name) < 0;
- }
- const file_entry* Zips::getEntryByName(const char* name)
- {
- if (_sort)
- {
- update();
- _sort = false;
- }
- files::const_iterator it = std::lower_bound(_files.begin(), _files.end(), name, findEntry);
- if (it != _files.end())
- {
- const file_entry& g = *it;
- if (!strcmp_cns(g.name, name))
- return &g;
- }
- return 0;
- }
- const file_entry* Zips::getEntry(int index)
- {
- if (_sort)
- {
- update();
- _sort = false;
- }
- return &_files[index];
- }
- size_t Zips::getNumEntries() const
- {
- return _files.size();
- }
- class fileHandleZip: public fileHandle
- {
- public:
- fileHandleZip(const file_entry* entry): _entry(entry)
- {
- int r = 0;
- r = unzGoToFilePos(entry->zp, const_cast<unz_file_pos*>(&entry->pos));
- OX_ASSERT(r == UNZ_OK);
- r = unzOpenCurrentFile(entry->zp);
- OX_ASSERT(r == UNZ_OK);
- }
- void release()
- {
- int r = unzCloseCurrentFile(_entry->zp);
- OX_ASSERT(r == UNZ_OK);
- delete this;
- }
- int seek(unsigned int offset, int whence)
- {
- OX_ASSERT(!"not implemented");
- return 0;
- }
- unsigned int tell() const
- {
- OX_ASSERT(!"not implemented");
- return 0;
- }
- unsigned int read(void* dest, unsigned int size)
- {
- return unzReadCurrentFile(_entry->zp, dest, size);
- }
- unsigned int write(const void* src, unsigned int size)
- {
- return 0;
- }
- unsigned int getSize() const
- {
- unz_file_info file_info;
- unzGetCurrentFileInfo(_entry->zp, &file_info, 0, 0, 0, 0, 0, 0);
- return (unsigned int) file_info.uncompressed_size;
- }
- const file_entry* _entry;
- };
- void ZipFileSystem::add(const char* zip)
- {
- log::messageln("ZipFileSystem::add %s", zip);
- _zips.add(zip);
- }
- void ZipFileSystem::add(const unsigned char* data, unsigned int size)
- {
- _zips.add(data, size);
- }
- void ZipFileSystem::add(std::vector<char>& data)
- {
- _zips.add(data);
- }
- void ZipFileSystem::reset()
- {
- _zips.reset();
- }
- FileSystem::status ZipFileSystem::_open(const char* file, const char* mode, error_policy ep, file::fileHandle*& fh)
- {
- const file_entry* entry = _zips.getEntryByName(file);
- if (entry)
- {
- fh = new fileHandleZip(entry);
- return status_ok;
- }
- handleErrorPolicy(ep, "can't find zip file entry: %s", file);
- return status_error;
- }
- FileSystem::status ZipFileSystem::_deleteFile(const char* file)
- {
- return status_error;
- }
- FileSystem::status ZipFileSystem::_makeDirectory(const char* file)
- {
- return status_error;
- }
- FileSystem::status ZipFileSystem::_deleteDirectory(const char* file)
- {
- return status_error;
- }
- FileSystem::status ZipFileSystem::_renameFile(const char* src, const char* dest)
- {
- return status_error;
- }
- }
- }
|