فهرست منبع

support streaming for zip file system

dmuratshin 9 سال پیش
والد
کامیت
8724edfc89
4فایلهای تغییر یافته به همراه118 افزوده شده و 1 حذف شده
  1. 82 1
      oxygine/src/core/ZipFileSystem.cpp
  2. 5 0
      oxygine/src/core/ZipFileSystem.h
  3. 28 0
      oxygine/src/minizip/unzip.c
  4. 3 0
      oxygine/src/minizip/unzip.h

+ 82 - 1
oxygine/src/core/ZipFileSystem.cpp

@@ -167,6 +167,8 @@ namespace oxygine
             zpfs.zseek_file = ox_fseek;
             zpfs.zclose_file = ox_fclose;
             zpfs.zerror_file = ox_ferror;
+            zpfs.opaque = (void*)_zps.size();
+            //zpfs.opaque = name;
 
             unzFile zp = unzOpen2(name, &zpfs);//todo, optimize search in zip
             OX_ASSERT(zp);
@@ -309,6 +311,81 @@ namespace oxygine
             }
 
             const file_entry* _entry;
+        };
+
+        class fileHandleZipStreaming : public fileHandle
+        {
+        public:
+            file::handle _h;
+            long _pos;
+            long _size;
+
+            fileHandleZipStreaming(const file_entry* entry, const Zips& z)
+            {
+                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* ptr;
+                r = unzRealTell(entry->zp, &_pos, &_size, &ptr);
+                OX_ASSERT(r == UNZ_OK);
+
+                zlib_filefunc_def* f = (zlib_filefunc_def*)ptr;
+                const char* ssss = z.getZipFileName((int)(size_t)f->opaque);
+
+                _h = file::open(ssss, "rb");
+                file::seek(_h, _pos, SEEK_SET);
+
+                unzCloseCurrentFile(entry->zp);
+            }
+
+            void release()
+            {
+                file::close(_h);
+                _h = 0;
+            }
+
+            unsigned int read(void* dest, unsigned int size)
+            {
+                return file::read(_h, dest, size);
+            }
+
+            unsigned int write(const void* src, unsigned int size)
+            {
+                OX_ASSERT(0);
+                return 0;
+            }
+
+            unsigned int getSize() const
+            {
+                return _size;
+            }
+
+            int          seek(unsigned int offset, int whence)
+            {
+                switch (whence)
+                {
+                    case SEEK_SET:
+                        return file::seek(_h, _pos + offset, SEEK_SET);
+                    case SEEK_CUR:
+                        return file::seek(_h, offset, SEEK_CUR);
+                    case SEEK_END:
+                        return file::seek(_h, offset, SEEK_END);
+                    default:
+                        break;
+                }
+                OX_ASSERT(0);
+                return 0;
+            }
+
+            unsigned int tell() const
+            {
+                return file::tell(_h) - _pos;
+            }
 
         };
 
@@ -329,6 +406,7 @@ namespace oxygine
             _zips.add(data);
         }
 
+
         void ZipFileSystem::reset()
         {
             _zips.reset();
@@ -339,7 +417,10 @@ namespace oxygine
             const file_entry* entry = _zips.getEntryByName(file);
             if (entry)
             {
-                fh = new fileHandleZip(entry);
+                if (*mode == '.')
+                    fh = new fileHandleZipStreaming(entry, _zips);
+                else
+                    fh = new fileHandleZip(entry);
                 return status_ok;
             }
 

+ 5 - 0
oxygine/src/core/ZipFileSystem.h

@@ -4,6 +4,7 @@
 #include "FileSystem.h"
 #include "minizip/unzip.h"
 #include "core/file.h"
+#include "core/Mutex.h"
 
 namespace oxygine
 {
@@ -37,6 +38,8 @@ namespace oxygine
             const file_entry*   getEntry(int index);
             size_t              getNumEntries() const;
 
+            const char* getZipFileName(int i) const { return _zps[i].name; }
+
         private:
             void read(unzFile zp);
 
@@ -55,6 +58,8 @@ namespace oxygine
             };
             typedef std::vector<zpitem> zips;
             zips _zps;
+
+            Mutex _lock;
         };
 
         bool read(file_entry* entry, file::buffer& bf);

+ 28 - 0
oxygine/src/minizip/unzip.c

@@ -1498,6 +1498,34 @@ extern z_off_t ZEXPORT unztell (file)
     return (z_off_t)pfile_in_zip_read_info->stream.total_out;
 }
 
+extern z_off_t ZEXPORT unzRealTell(file, pos, size, fs)
+unzFile file;
+z_off_t* pos;
+z_off_t* size;
+voidp* fs;
+{
+	unz_s* s;
+	file_in_zip_read_info_s* pfile_in_zip_read_info;
+
+	if (file == NULL)
+		return UNZ_PARAMERROR;
+
+	s = (unz_s*)file;
+	pfile_in_zip_read_info = s->pfile_in_zip_read;
+
+	if (pfile_in_zip_read_info == NULL)
+		return UNZ_PARAMERROR;
+
+	if (pfile_in_zip_read_info->rest_read_compressed != pfile_in_zip_read_info->rest_read_uncompressed)
+		return UNZ_PARAMERROR;
+
+	*pos = pfile_in_zip_read_info->pos_in_zipfile;
+	*size = pfile_in_zip_read_info->rest_read_compressed;
+	*fs = &pfile_in_zip_read_info->z_filefunc;
+
+	return UNZ_OK;
+}
+
 
 /*
   return 1 if the end of file was reached, 0 elsewhere

+ 3 - 0
oxygine/src/minizip/unzip.h

@@ -318,6 +318,9 @@ extern int ZEXPORT unzReadCurrentFile OF((unzFile file,
 */
 
 extern z_off_t ZEXPORT unztell OF((unzFile file));
+
+extern int ZEXPORT unzRealTell OF((unzFile file, z_off_t* pos, z_off_t* size, voidp* fs));
+
 /*
   Give the current position in uncompressed data
 */