- Support for Zip Filesystem. It is now possible to zip the entire Res folder ("store" method preferred, zip so that the root of the zip has ai, player, etc...) in one single file for read only. Write access is done in another folder (hardcoded to be User/ for now, can be updated depending on platforms, etc...

-- zipFS has several limitations...
--- in a general way, seekg doesn't work... so getting a file's size needs to be done through JFileSystem.
--- getLine on files open with zipFS doesn't work so great. Not sure if it is a normal issue because files are open in binary or not... JFileSystem therefore offers a "readIntoString" function that needs to be used instead of the usual "getline" technique. However getLine can then be used on a stream connected to the string.

-- tested on Windows and PSP, I also made sure android still works, but haven't tested zip support on Android.
-- I tried to maintain backwards compatibility, but this might break on some platforms, if I broke some platforms and you can't find a way to fix them, please contact me and we'll figure something out
-- This removes wagic::ifstream. I didn't reimplement the securities that were involved in this, apologies for that. Might be useful to reimplement such securities in JFileSystem
-- I haven't tested options/profiles in a deep way, it is possible I broke that.
This commit is contained in:
wagic.the.homebrew
2011-08-21 09:04:59 +00:00
parent 14bd7b7a24
commit e27cf56fa2
73 changed files with 3539 additions and 936 deletions

View File

@@ -100,7 +100,7 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>Dependencies/SDL/include;Dependencies/include;$(JGEEXTRAS);../Boost;../projects/mtg/include;include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>src/zipFS;Dependencies/SDL/include;Dependencies/include;$(JGEEXTRAS);../Boost;../projects/mtg/include;include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>SDL_CONFIG;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
@@ -182,18 +182,7 @@
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<ClCompile Include="src\JFileSystem.cpp">
<Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Disabled</Optimization>
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">EnableFastChecks</BasicRuntimeChecks>
<Optimization Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">MaxSpeed</Optimization>
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Optimization Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">MaxSpeed</Optimization>
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<ClCompile Include="src\JFileSystem.cpp" />
<ClCompile Include="src\JGameObject.cpp">
<Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Disabled</Optimization>
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
@@ -281,6 +270,7 @@
</ClCompile>
<ClCompile Include="src\JTTFont.cpp" />
<ClCompile Include="src\SDLmain.cpp" />
<ClCompile Include="src\tinyxml\tinyxmlparser.cpp" />
<ClCompile Include="src\Vector2D.cpp">
<Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Disabled</Optimization>
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
@@ -300,46 +290,12 @@
<ClCompile Include="src\hge\hgepmanager.cpp" />
<ClCompile Include="src\hge\hgerect.cpp" />
<ClCompile Include="src\hge\hgevector.cpp" />
<ClCompile Include="src\unzip\ioapi.c">
<Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Disabled</Optimization>
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">EnableFastChecks</BasicRuntimeChecks>
<Optimization Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">MaxSpeed</Optimization>
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Optimization Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">MaxSpeed</Optimization>
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<ClCompile Include="src\unzip\mztools.c">
<Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Disabled</Optimization>
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">EnableFastChecks</BasicRuntimeChecks>
<Optimization Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">MaxSpeed</Optimization>
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Optimization Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">MaxSpeed</Optimization>
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<ClCompile Include="src\unzip\unzip.c">
<Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Disabled</Optimization>
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">EnableFastChecks</BasicRuntimeChecks>
<Optimization Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">MaxSpeed</Optimization>
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Optimization Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">MaxSpeed</Optimization>
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<ClCompile Include="src\tinyxml\tinystr.cpp" />
<ClCompile Include="src\tinyxml\tinyxml.cpp" />
<ClCompile Include="src\tinyxml\tinyxmlerror.cpp" />
<ClCompile Include="src\tinyxml\tinyxmlparser.cpp" />
<ClCompile Include="src\zipFS\zfsystem.cpp" />
<ClCompile Include="src\zipFS\ziphdr.cpp" />
<ClCompile Include="src\zipFS\zstream.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="include\DebugRoutines.h" />
@@ -383,12 +339,15 @@
<ClInclude Include="include\hge\hgeparticle.h" />
<ClInclude Include="include\hge\hgerect.h" />
<ClInclude Include="include\hge\hgevector.h" />
<ClInclude Include="src\unzip\crypt.h" />
<ClInclude Include="src\unzip\ioapi.h" />
<ClInclude Include="src\unzip\mztools.h" />
<ClInclude Include="src\unzip\unzip.h" />
<ClInclude Include="src\tinyxml\tinystr.h" />
<ClInclude Include="src\tinyxml\tinyxml.h" />
<ClInclude Include="src\zipFS\fileio.h" />
<ClInclude Include="src\zipFS\static_assert.h" />
<ClInclude Include="src\zipFS\stdafx.h" />
<ClInclude Include="src\zipFS\zfsystem.h" />
<ClInclude Include="src\zipFS\ziphdr.h" />
<ClInclude Include="src\zipFS\zstream.h" />
<ClInclude Include="src\zipFS\zstream_zlib.h" />
</ItemGroup>
<ItemGroup>
<None Include="Makefile" />

View File

@@ -15,7 +15,7 @@ GENERIC_OBJS = src/JApp.o src/JGBKFont.o \
src/JNetwork.o \
src/JParticle.o src/JParticleEmitter.o src/JParticleEffect.o \
src/JParticleSystem.o \
src/unzip/ioapi.o src/unzip/mztools.o src/unzip/unzip.o \
src/zipFS/zfsystem.o src/zipFS/ziphdr.o src/zipFS/zstream.o \
src/JSprite.o src/Vector2D.o \
src/tinyxml/tinystr.o src/tinyxml/tinyxml.o \
src/tinyxml/tinyxmlparser.o src/tinyxml/tinyxmlerror.o \
@@ -73,7 +73,7 @@ PSPSDK = $(shell psp-config --pspsdk-path)
PSPDIR = $(shell psp-config --psp-prefix)
OBJS = $(GENERIC_OBJS) $(PSP_OBJS)
TARGET_HGE = libhgetools.a
INCDIR = include/psp include/psp/freetype2 ../Boost
INCDIR = include/psp include/psp/freetype2 ../Boost src/zipFS
CXXFLAGS += -O2 -G0 -DPSP
LIBDIR = lib/psp
endif

View File

@@ -6,7 +6,7 @@ OBJS = src/hge/hgecolor.o src/hge/hgeparticle.o \
src/hge/hgedistort.o src/hge/hgefont.o
INCDIR = include/psp include/psp/freetype2
INCDIR = include/psp include/psp/freetype2 src/zipFS
LIBDIR = lib/psp
CFLAGS = -O2 -G0 -Wall

View File

@@ -1,28 +1,11 @@
//-------------------------------------------------------------------------------------
//
// JGE++ is a hardware accelerated 2D game SDK for PSP/Windows.
//
// Licensed under the BSD license, see LICENSE in JGE root for details.
//
// Copyright (c) 2007 James Hui (a.k.a. Dr.Watson) <jhkhui@gmail.com>
//
//-------------------------------------------------------------------------------------
#ifndef _J_FILE_SYSTEM_H_
#define _J_FILE_SYSTEM_H_
#ifndef _FILE_SYSTEM_H_
#define _FILE_SYSTEM_H_
#define JGE_GET_RES(filename) JFileSystem::GetInstance()->GetResourceFile(filename)
#define JGE_GET_RESPATH() JFileSystem::GetInstance()->GetResourceRoot()
#include <stdio.h>
#include <vector>
#include <map>
#include "zfsystem.h"
#include <string>
#if defined (PSP)
#include <pspiofilemgr.h>
#include <pspiofilemgr_fcntl.h>
#endif
using zip_file_system::filesystem;
using zip_file_system::izfstream;
using namespace std;
#include "unzip/unzip.h"
@@ -40,22 +23,30 @@ class JZipCache {
public:
JZipCache();
~JZipCache();
map<string,unz_file_pos *> dir;
map<string, filesystem::file_info> dir;
};
class JFileSystem
{
class JFileSystem {
private:
string mSystemFSPath, mUserFSPath;
filesystem * mSystemFS, * mUserFS;
static JFileSystem* mInstance;
izfstream mFile;
map<string,JZipCache *>mZipCache;
string mZipFileName;
int mFileSize;
char *mPassword;
bool mZipAvailable;
void preloadZip(const string& filename);
izfstream mZipFile;
filesystem::file_info * mCurrentFileInZip;
std::vector<std::string>& scanRealFolder(const std::string& folderName, std::vector<std::string>& results);
public:
//////////////////////////////////////////////////////////////////////////
/// Get the singleton instance
///
//////////////////////////////////////////////////////////////////////////
static JFileSystem* GetInstance();
static void Destroy();
//////////////////////////////////////////////////////////////////////////
/// Attach ZIP archive to the file system.
@@ -74,12 +65,26 @@ public:
//////////////////////////////////////////////////////////////////////////
void DetachZipFile();
// Manually Clear the zip cache
void clearZipCache();
//////////////////////////////////////////////////////////////////////////
/// Get the singleton instance
///
//////////////////////////////////////////////////////////////////////////
static JFileSystem* GetInstance();
static void Destroy();
//////////////////////////////////////////////////////////////////////////
/// Open file for reading.
///
//////////////////////////////////////////////////////////////////////////
bool OpenFile(const string &filename);
//Fills the vector results with a list of children of the given folder
std::vector<std::string>& scanfolder(const std::string& folderName, std::vector<std::string>& results);
std::vector<std::string> scanfolder(const std::string& folderName);
//////////////////////////////////////////////////////////////////////////
/// Read data from file.
///
@@ -96,6 +101,7 @@ public:
///
//////////////////////////////////////////////////////////////////////////
int GetFileSize();
int GetFileSize(izfstream & file);
//////////////////////////////////////////////////////////////////////////
/// Close file.
@@ -109,37 +115,47 @@ public:
/// @resourceRoot - New root.
///
//////////////////////////////////////////////////////////////////////////
void SetResourceRoot(const string& resourceRoot);
string GetResourceRoot();
void SetSystemRoot(const string& resourceRoot);
string GetSystemRoot() { return mSystemFSPath; };
// Returns a string prefixed with the resource path
string GetResourceFile(string filename);
void SetUSerRoot(const string& resourceRoot);
string GetUserRoot() { return mUserFSPath; };
bool openForRead(izfstream & File, const string & FilePath);
bool readIntoString(const string & FilePath, string & target);
bool openForWrite(ofstream & File, const string & FilePath, ios_base::openmode mode = ios_base::out );
bool Rename(string from, string to);
//Returns true if strFilename exists somewhere in the fileSystem
bool FileExists(const string& strFilename);
//Returns true if strdirname exists somewhere in the fileSystem, and is a directory
bool DirExists(const string& strDirname);
static void init( const string & userPath, const string & systemPath = "");
// AVOID Using This function!!!
/*
This function is deprecated, but some code is still using it
It used to give a pathname to a file in the file system.
Now with the support of zip resources, a pathname does not make sense anymore
However some of our code still relies on "physical" files not being in zip.
So this call is now super heavy: it checks where the file is, and if it's in a zip, it extracts
it to the user Filesystem, assuming that whoever called this needs to access the file through its pathname later on
*/
string GetResourceFile(string filename);
// Manually Clear the zip cache
void clearZipCache();
protected:
JFileSystem();
JFileSystem(const string & userPath, const string & systemPath = "");
~JFileSystem();
private:
static JFileSystem* mInstance;
map<string,JZipCache *>mZipCache;
string mResourceRoot;
string mZipFileName;
char *mPassword;
bool mZipAvailable;
void preloadZip(const string& filename);
#if defined (PSP)
SceUID mFile;
#else
FILE *mFile;
#endif
unzFile mZipFile;
int mFileSize;
};
#endif
#endif

View File

@@ -3,7 +3,9 @@
//logging facility
//#define DOLOG
#ifdef DOLOG
#include <string>
//The PSP one is to log stuff in JLogger's lastLog, it does not do full log in a text file unless DOLOG is defined
#if defined(DOLOG) || defined (PSP)
#define LOG(x) JLogger::Log(x);
#else
#define LOG(x) {};
@@ -22,6 +24,8 @@ class JLogger{
~JLogger();
const char* mText;
static std::string lastLog;
};
#endif

View File

@@ -1,12 +1,21 @@
//-------------------------------------------------------------------------------------
//
// JGE++ is a hardware accelerated 2D game SDK for PSP/Windows.
//
// Licensed under the BSD license, see LICENSE in JGE root for details.
//
// Copyright (c) 2007 James Hui (a.k.a. Dr.Watson) <jhkhui@gmail.com>
//
//-------------------------------------------------------------------------------------
/* JFileSystem centralizes all access to resources in JGE.
It allows to have files for the game split in two subfolders, a "system" subfolder (read only) and a "user" subfolder (read/write)
Additionally, these two subfolders can have some of their resources in zip file (see zfsystem.h).
Zip files can contain duplicates of the same file, the one that will eventually be used is the one is the latest zip file (by alphabetical order)
Read access priority:
User folder, real file
User folder, zip file
System folder, real file
System folder, zip file
Write access:
User folder, real file
User folder is the only one that is really needed to guarantee both read and write access, the system folder is not necessary but provides a nice way to distinguish
The content that users should not be touching.
*/
#ifdef WIN32
#pragma warning(disable : 4786)
@@ -15,26 +24,15 @@
#include "../include/JGE.h"
#include "../include/JFileSystem.h"
#include "../include/JLogger.h"
#include "tinyxml/tinyxml.h"
#include "unzip/unzip.h"
#include <stdio.h>
#include <vector>
#include <map>
#include <string>
#include <dirent.h>
JFileSystem* JFileSystem::mInstance = NULL;
JZipCache::JZipCache()
{}
JZipCache::~JZipCache()
{
map<string,unz_file_pos *>::iterator it;
for (it = dir.begin(); it != dir.end(); ++it)
{
delete(it->second);
}
dir.clear();
}
@@ -46,38 +44,115 @@ void JFileSystem::preloadZip(const string& filename)
JZipCache * cache = new JZipCache();
mZipCache[filename] = cache;
if (!mZipAvailable || !mZipFile)
if (!mZipAvailable || !mZipFile) {
AttachZipFile(filename);
if (!mZipAvailable || !mZipFile) return;
}
if (! (mUserFS->PreloadZip(filename.c_str(), cache->dir) || (mSystemFS && mSystemFS->PreloadZip(filename.c_str(), cache->dir))))
{
AttachZipFile(filename);
if (!mZipAvailable || !mZipFile) return;
}
int err = unzGoToFirstFile (mZipFile);
while (err == UNZ_OK)
{
unz_file_pos* filePos = new unz_file_pos();
char filenameInzip[4096];
if (unzGetCurrentFileInfo(mZipFile, NULL, filenameInzip, sizeof(filenameInzip), NULL, 0, NULL, 0) == UNZ_OK)
{
unzGetFilePos(mZipFile, filePos);
string name = filenameInzip;
cache->dir[name] = filePos;
}
err = unzGoToNextFile(mZipFile);
DetachZipFile();
}
}
JFileSystem* JFileSystem::mInstance = NULL;
void JFileSystem::init(const string & userPath, const string & systemPath)
{
Destroy();
mInstance = new JFileSystem(userPath, systemPath);
}
JFileSystem* JFileSystem::GetInstance()
{
if (mInstance == NULL)
if (!mInstance)
{
mInstance = new JFileSystem();
#ifdef RESPATH
init( RESPATH"/");
#else
init("Res/");
}
#endif
return mInstance;
}
// Tries to set the system and user paths.
// On some OSes, the parameters get overriden by hardcoded values
JFileSystem::JFileSystem(const string & _userPath, const string & _systemPath)
{
string systemPath = _systemPath;
string userPath = _userPath;
#ifdef IOS
//copy the RES folder over to the Documents folder
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentsDirectory = [[paths objectAtIndex:0] stringByAppendingString: @"/Res"];
NSString *resourceDBFolderPath = [[[NSBundle mainBundle] resourcePath]
stringByAppendingPathComponent:@"Res"];
// copy the Res folder over to the Documents directory if it doesn't exist.
if ( ![fileManager fileExistsAtPath: documentsDirectory])
[fileManager copyItemAtPath:resourceDBFolderPath toPath:documentsDirectory error:&error];
userPath = [documentsDirectory cStringUsingEncoding:1];
userPath += "/";
systemPath = "";
#elif defined (ANDROID)
userPath = "/sdcard/Wagic/Res/";
systemPath = "";
#else
//Find the Res.txt file and matching Res folders for backwards compatibility
ifstream mfile("Res.txt");
string resPath;
if (mfile)
{
bool found = false;
while (!found && std::getline(mfile, resPath))
{
if (resPath[resPath.size() - 1] == '\r')
resPath.erase(resPath.size() - 1); //Handle DOS files
string testfile = resPath;
testfile.append("graphics/simon.dat");
ifstream file(testfile.c_str());
if (file)
{
userPath = resPath;
systemPath = "";
found = true;
file.close();
}
}
mfile.close();
}
#endif
// Make sure the base paths finish with a '/' or a '\'
if (! userPath.empty()) {
string::iterator c = --(userPath.end());
if ((*c != '/') && (*c != '\\'))
userPath += '/';
}
if (! systemPath.empty()) {
string::iterator c = --(systemPath.end());
if ((*c != '/') && (*c != '\\'))
systemPath += '/';
}
mUserFSPath = userPath;
mSystemFSPath = systemPath;
mUserFS = new filesystem(userPath.c_str());
mSystemFS = (mSystemFSPath.size() && (mSystemFSPath.compare(mUserFSPath) != 0)) ? new filesystem(systemPath.c_str()) : NULL;
mZipAvailable = false;
mPassword = NULL;
mFileSize = 0;
mCurrentFileInZip = NULL;
};
void JFileSystem::Destroy()
{
@@ -88,32 +163,29 @@ void JFileSystem::Destroy()
}
}
JFileSystem::JFileSystem()
{
mZipAvailable = false;
#if defined (PSP)
mFile = -1;
#else
mFile = NULL;
#endif
mPassword = NULL;
mZipFile = NULL;
mFileSize = 0;
#ifdef RESPATH
SetResourceRoot(RESPATH"/");
#else
SetResourceRoot("Res/"); // default root folder
#endif
bool JFileSystem::DirExists(const string& strDirname)
{
return mUserFS->DirExists(strDirname) || (mSystemFS && mSystemFS->DirExists(strDirname));
}
bool JFileSystem::FileExists(const string& strFilename)
{
izfstream temp;
bool result = openForRead(temp, strFilename);
if (temp)
temp.close();
return result;
}
JFileSystem::~JFileSystem()
{
clearZipCache();
SAFE_DELETE(mUserFS);
SAFE_DELETE(mSystemFS);
}
void JFileSystem::clearZipCache()
{
DetachZipFile();
@@ -138,166 +210,313 @@ bool JFileSystem::AttachZipFile(const string &zipfile, char *password /* = NULL
mZipFileName = zipfile;
mPassword = password;
mZipFile = unzOpen(mZipFileName.c_str());
openForRead(mZipFile, mZipFileName);
if (mZipFile != NULL)
if (!mZipFile)
return false;
//A hack for a zip inside a zip: instead we open the zip containing it
if (mZipFile.Zipped())
{
mZipAvailable = true;
return true;
mZipFile.close();
assert(filesystem::getCurrentFS());
mZipFile.open(filesystem::getCurrentZipName().c_str(), filesystem::getCurrentFS());
assert(mZipFile);
}
mZipAvailable = true;
return true;
return false;
}
void JFileSystem::DetachZipFile()
{
if (mZipAvailable && mZipFile != NULL)
if (mZipFile)
{
int error = unzCloseCurrentFile(mZipFile);
if (error < 0 )
JLOG("error calling unzCloseCurrentFile");
error = unzClose(mZipFile);
if (error < 0)
JLOG("Error calling unzClose");
mZipFile.close();
}
mZipFile = NULL;
mCurrentFileInZip = NULL;
mZipAvailable = false;
}
bool JFileSystem::openForRead(izfstream & File, const string & FilePath) {
File.open(FilePath.c_str(), mUserFS);
if (File)
return true;
if(!mSystemFS)
return false;
File.open(FilePath.c_str(), mSystemFS);
if (File)
return true;
return false;
}
bool JFileSystem::readIntoString(const string & FilePath, string & target)
{
izfstream file;
if (!openForRead(file, FilePath))
return false;
int fileSize = GetFileSize(file);
target.resize((std::string::size_type) fileSize);
if (fileSize)
file.read(&target[0], fileSize);
file.close();
return true;
}
bool JFileSystem::openForWrite(ofstream & File, const string & FilePath, ios_base::openmode mode)
{
string filename = mUserFSPath;
filename.append(FilePath);
File.open(filename.c_str(), mode);
if (File)
{
return true;
}
return false;
}
bool JFileSystem::OpenFile(const string &filename)
{
string path = mResourceRoot + filename;
mCurrentFileInZip = NULL;
if (mZipAvailable && mZipFile != NULL)
if (!mZipAvailable || !mZipFile)
return openForRead(mFile, filename);
preloadZip(mZipFileName);
map<string,JZipCache *>::iterator it = mZipCache.find(mZipFileName);
if (it == mZipCache.end())
{
preloadZip(mZipFileName);
map<string,JZipCache *>::iterator it = mZipCache.find(mZipFileName);
if (it == mZipCache.end())
{
DetachZipFile();
return OpenFile(filename);
}
JZipCache * zc = it->second;
map<string,unz_file_pos *>::iterator it2 = zc->dir.find(filename);
if (it2 == zc->dir.end())
{
DetachZipFile();
return OpenFile(filename);
}
unzGoToFilePos(mZipFile,it2->second);
char filenameInzip[256];
unz_file_info fileInfo;
if (unzGetCurrentFileInfo(mZipFile, &fileInfo, filenameInzip, sizeof(filenameInzip), NULL, 0, NULL, 0) == UNZ_OK)
mFileSize = fileInfo.uncompressed_size;
else
mFileSize = 0;
return (unzOpenCurrentFilePassword(mZipFile, mPassword) == UNZ_OK);
//DetachZipFile();
//return OpenFile(filename);
return openForRead(mFile, filename);
}
else
JZipCache * zc = it->second;
map<string, filesystem::file_info>::iterator it2 = zc->dir.find(filename);
if (it2 == zc->dir.end())
{
#if defined (PSP)
mFile = sceIoOpen(path.c_str(), PSP_O_RDONLY, 0777);
if (mFile > 0)
{
mFileSize = sceIoLseek(mFile, 0, PSP_SEEK_END);
sceIoLseek(mFile, 0, PSP_SEEK_SET);
return true;
}
#else
mFile = fopen(path.c_str(), "rb");
if (mFile != NULL)
{
fseek(mFile, 0, SEEK_END);
mFileSize = ftell(mFile);
fseek(mFile, 0, SEEK_SET);
return true;
}
#endif
/*DetachZipFile();
return OpenFile(filename); */
return openForRead(mFile, filename);
}
return false;
mCurrentFileInZip = &(it2->second);
mFileSize = it2->second.m_Size;
return true;
}
void JFileSystem::CloseFile()
{
if (mZipAvailable && mZipFile != NULL)
if (mZipAvailable && mZipFile)
{
unzCloseCurrentFile(mZipFile);
return;
mCurrentFileInZip = NULL;
}
#if defined (PSP)
if (mFile > 0)
sceIoClose(mFile);
#else
if (mFile != NULL)
fclose(mFile);
#endif
if (mFile)
mFile.close();
}
//returns 0 if less than "size" bits were read
int JFileSystem::ReadFile(void *buffer, int size)
{
if (mZipAvailable && mZipFile != NULL)
{
return unzReadCurrentFile(mZipFile, buffer, size);
}
else
{
#if defined (PSP)
return sceIoRead(mFile, buffer, size);
#else
return fread(buffer, 1, size, mFile);
#endif
}
if (mCurrentFileInZip)
{
assert(mZipFile);
if((size_t)size > mCurrentFileInZip->m_CompSize) //only support "store" method for zip inside zips
return 0;
std::streamoff offset = filesystem::SkipLFHdr(mZipFile, mCurrentFileInZip->m_Offset);
if (!mZipFile.seekg(offset))
return 0;
mZipFile.read((char *) buffer, size);
//TODO what if can't read
return size;
}
if (!mFile)
return 0;
assert(!mFile.Zipped() || (size_t)size <= mFile.getUncompSize());
mFile.read((char *)buffer, size);
if (mFile.eof())
return 0;
return size;
}
std::vector<std::string>& JFileSystem::scanRealFolder(const std::string& folderName, std::vector<std::string>& results)
{
DIR *dip = opendir(folderName.c_str());
if (!dip)
return results;
while (struct dirent * dit = readdir(dip))
{
results.push_back(dit->d_name);
}
closedir(dip);
return results;
}
std::vector<std::string>& JFileSystem::scanfolder(const std::string& _folderName, std::vector<std::string>& results)
{
if (!_folderName.size())
return results;
map<string, bool> seen;
string folderName = _folderName;
if (folderName[folderName.length() - 1] != '/')
folderName.append("/");
//user filesystem
{
//Scan the zip filesystem
std::vector<std::string> userZips;
mUserFS->scanfolder(folderName, userZips);
for (size_t i = 0; i < userZips.size(); ++i)
seen[userZips[i]] = true;
//scan the real files
//TODO check for "/"
std::vector<std::string> userReal;
string realFolderName = mUserFSPath;
realFolderName.append(folderName);
scanRealFolder(realFolderName, userReal);
for (size_t i = 0; i < userReal.size(); ++i)
seen[userReal[i]] = true;
}
if (mSystemFS)
{
//Scan the zip filesystem
std::vector<std::string> systemZips;
mSystemFS->scanfolder(folderName, systemZips);
for (size_t i = 0; i < systemZips.size(); ++i)
seen[systemZips[i]] = true;
//scan the real files
//TODO check for "/"
std::vector<std::string> systemReal;
string realFolderName = mSystemFSPath;
realFolderName.append(folderName);
scanRealFolder(realFolderName, systemReal);
for (size_t i = 0; i < systemReal.size(); ++i)
seen[systemReal[i]] = true;
}
for(map<string,bool>::iterator it = seen.begin(); it != seen.end(); ++it)
{
results.push_back(it->first);
}
return results;
}
std::vector<std::string> JFileSystem::scanfolder(const std::string& folderName)
{
std::vector<std::string> result;
return scanfolder(folderName, result);
}
int JFileSystem::GetFileSize()
{
return mFileSize;
if (mCurrentFileInZip)
return mFileSize;
return GetFileSize(mFile);
}
void JFileSystem::SetResourceRoot(const string& resourceRoot)
bool JFileSystem::Rename(string _from, string _to)
{
#ifdef IOS
//copy the RES folder over to the Documents folder
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentsDirectory = [[paths objectAtIndex:0] stringByAppendingString: @"/Res"];
NSString *resourceDBFolderPath = [[[NSBundle mainBundle] resourcePath]
stringByAppendingPathComponent:@"Res"];
// copy the Res folder over to the Documents directory if it doesn't exist.
if ( ![fileManager fileExistsAtPath: documentsDirectory])
[fileManager copyItemAtPath:resourceDBFolderPath toPath:documentsDirectory error:&error];
mResourceRoot = [documentsDirectory cStringUsingEncoding:1];
mResourceRoot += "/";
#elif defined (ANDROID)
mResourceRoot = "/sdcard/Wagic/Res/";
#else
mResourceRoot = resourceRoot;
#endif
string from = mUserFSPath + _from;
string to = mUserFSPath + _to;
std::remove(to.c_str());
return rename(from.c_str(), to.c_str()) ? true: false;
}
string JFileSystem::GetResourceRoot()
int JFileSystem::GetFileSize(izfstream & file)
{
return mResourceRoot;
if (!file)
return 0;
if (file.Zipped())
{
//There's a bug in zipped version that prevents from sending a correct filesize with the "standard" seek method
//The hack below only works for the "stored" version I think...
return file.getUncompSize();
}
file.seekg (0, ios::end);
int length = (int) file.tellg();
file.seekg (0, ios::beg);
return length;
}
// AVOID Using This function!!!
/*
This function is deprecated, but some code is still using it
It used to give a pathname to a file in the file system.
Now with the support of zip resources, a pathname does not make sense anymore
However some of our code still relies on "physical" files not being in zip.
So this call is now super heavy: it checks where the file is, and if it's in a zip, it extracts
it to the user Filesystem, assuming that whoever called this needs to access the file through its pathname later on.
As a result, this function isvery inefficient and shouldn't be used in the general case.
*/
string JFileSystem::GetResourceFile(string filename)
{
string result = mResourceRoot;
return result.append(filename);
izfstream temp;
bool result = openForRead(temp, filename);
if (!temp || !result)
return "";
if (!temp.Zipped())
{
string result = temp.FullFilePath();
temp.close();
return result;
}
// File is inside a zip archive,
//we copy it to the user FS
string destFile = mUserFSPath + filename;
ofstream dest;
if (openForWrite(dest, filename, ios_base::binary))
{
// allocate memory:
size_t length = temp.getUncompSize();
char * buffer = new char [length];
// read data as a block:
temp.read(buffer, length);
temp.close();
dest.write (buffer,length);
delete[] buffer;
dest.close();
return destFile;
}
return "";
}

View File

@@ -1024,8 +1024,6 @@ void JRenderer::LoadJPG(TextureInfo &textureInfo, const char *filename, int mode
{
JLOG("JRenderer::LoadJPG");
textureInfo.mBits = NULL;
char filenamenew[4096];
sprintf(filenamenew, JGE_GET_RES(filename).c_str());
bool useVideoRAM = (mode == TEX_TYPE_USE_VRAM);

View File

@@ -3,7 +3,10 @@
#include <fstream>
string JLogger::lastLog = "";
void JLogger::Log(const char * text){
#ifdef DOLOG
std::ofstream file(LOG_FILE, std::ios_base::app);
if (file){
file << text;
@@ -12,6 +15,8 @@ void JLogger::Log(const char * text){
}
DebugTrace(text);
#endif
lastLog = text;
}
JLogger::JLogger(const char* text) : mText(text)

View File

@@ -110,7 +110,7 @@ void JSoundSystem::DestroySoundSystem()
JMusic *JSoundSystem::LoadMusic(const char *fileName)
{
string s = JGE_GET_RES(fileName);
string s = JFileSystem::GetInstance()->GetResourceFile(fileName);
JMusic *music = new JMusic();
if (music)

View File

@@ -70,7 +70,7 @@ hgeParticleSystem::hgeParticleSystem(const char *filename, JQuad *sprite)
// we're actually trying to read more than the file size now, but it's no problem.
// Note that this fix is only to avoid the largest problems, filling a structure
// by directly reading a file, is really a bad idea ...
fileSys->ReadFile(&(info.nEmission), sizeof(hgeParticleSystemInfo));
fileSys->ReadFile(&(info.nEmission), sizeof(hgeParticleSystemInfo) - 4);
fileSys->CloseFile();
info.sprite=sprite;

View File

@@ -149,6 +149,7 @@ void ExceptionHandler(PspDebugRegBlock * regs)
pspDebugScreenPrintf("Your PSP has just crashed!\n");
pspDebugScreenPrintf("Exception details:\n\n");
pspDebugScreenPrintf("Last Log Message: \n%s\n\n", JLogger::lastLog.c_str());
pspDebugScreenPrintf("Exception - %s\n", codeTxt[(regs->cause >> 2) & 31]);
pspDebugScreenPrintf("EPC - %08X / %s.text + %08X\n", (int)regs->epc, module_info.modname, (unsigned int)(regs->epc-(int)&_ftext));
pspDebugScreenPrintf("Cause - %08X\n", (int)regs->cause);

25
JGE/src/zipFS/Makefile Normal file
View File

@@ -0,0 +1,25 @@
MAIN=zfs
CC=g++
CFLAGS= -O2 -Wall -DNDEBUG -DUNIX
INCLUDES=
LFLAGS= -lz
SRCS = \
zfs.cpp \
zfsystem.cpp \
ziphdr.cpp \
zstream.cpp \
OBJS = $(SRCS:.cpp=.o)
$(MAIN): $(OBJS)
$(CC) -o $(MAIN) $(LFLAGS) $(OBJS)
.cpp.o:
$(CC) $(CFLAGS) $(INCLUDES) -c $<
clean:
rm -f *.o $(MAIN)

Binary file not shown.

Binary file not shown.

252
JGE/src/zipFS/fileio.h Normal file
View File

@@ -0,0 +1,252 @@
// bfileio.h: interface for the binary file i/o.
//
//////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2004 Tanguy Fautré.
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
// Tanguy Fautré
// softdev@telenet.be
//
//////////////////////////////////////////////////////////////////////
//
// File I/O Facilities.
// ********************
//
// Current version: 1.00 BETA 4 (16/07/2004)
//
// Comment: readvar() and writevar() read a little endian ordered
// value on a file and put it in a variable.
// search_iterator only accepts "<directory>/*.<ext>".
// Uses ANSI C "assert()". Define NDEBUG to turn it off.
// (note: Visual C++ define NDEBUG in Release mode)
//
// History: - 1.00 BETA 4 (16/07/2004) - Fixed small bug in UNIX search_iterator
// - 1.00 BETA 3 (27/06/2004) - Added UNIX compatibility
// - 1.00 BETA 2 (21/02/2003) - Now endianess independent
// - 1.00 BETA 1 (06/09/2002) - First public release
//
//////////////////////////////////////////////////////////////////////
#pragma once
#if defined WIN32
#include <io.h> // Windows I/O facilities (Directories)
#else
#include <dirent.h>
#include <string.h>
#endif
#include <limits.h>
namespace io_facilities {
// Global function for reading binary variables
template <class T> std::istream & readvar(std::istream & File, T & Var, const std::streamsize NbBytes);
template <class T> std::ostream & writevar(std::ostream & File, const T & Var, const std::streamsize NbBytes);
// Class for searching files and directories
// (!!! not compliant with C++ std::iterator and is thus meant for specific use !!!)
class search_iterator
{
public:
search_iterator();
search_iterator(const char * FileSpec);
~search_iterator();
operator bool () const;
search_iterator & operator ++ ();
search_iterator & begin(const char * FileSpec);
search_iterator & next();
bool end() const;
std::string Name() const;
protected:
bool m_Valid;
#if defined WIN32
intptr_t m_hFiles;
_finddata_t m_FindData;
#else
DIR * m_Directory;
std::string m_Extension;
struct dirent * m_DirectoryEntry;
#endif
};
//////////////////////////////////////////////////////////////////////
// io_facilities:: Inline Functions
//////////////////////////////////////////////////////////////////////
template <class T>
inline std::istream & readvar(std::istream & File, T & Var, const std::streamsize NbBytes)
{
// Debug test to ensure type size is big enough
assert(sizeof(T) >= size_t(NbBytes));
// Var = 0 ensure type size won't matter
T TmpVar = Var = 0;
for (std::streamsize i = 0; i < NbBytes; ++i) {
File.read(reinterpret_cast<char *>(&TmpVar), 1);
Var |= TmpVar << (i * CHAR_BIT);
}
return File;
}
template <class T>
inline std::ostream & writevar(std::ostream & File, const T & Var, const std::streamsize NbBytes)
{
// Debug test to ensure type size is big enough
assert(sizeof(T) >= size_t(NbBytes));
T TmpVar = Var;
for (std::streamsize i = 0; i < NbBytes; ++i)
File.write(reinterpret_cast<const char *>(&(TmpVar >>= (CHAR_BIT * i))), 1);
return File;
}
//////////////////////////////////////////////////////////////////////
// io_facilities::search_iterator Inline Member Functions
//////////////////////////////////////////////////////////////////////
inline search_iterator::search_iterator()
: m_Valid(false),
#if defined WIN32
m_hFiles(-1)
#else
m_Directory(NULL)
#endif
{ }
inline search_iterator::search_iterator(const char * FileSpec)
: m_Valid(false),
#if defined WIN32
m_hFiles(-1)
#else
m_Directory(NULL)
#endif
{
begin(FileSpec);
}
inline search_iterator::~search_iterator() {
#if defined WIN32
if (m_hFiles != -1) _findclose(m_hFiles);
#else
if (m_Directory != NULL) closedir(m_Directory);
#endif
}
inline search_iterator::operator bool () const {
return m_Valid;
}
inline search_iterator & search_iterator::operator ++ () {
return next();
}
inline search_iterator & search_iterator::begin(const char * FileSpec) {
#if defined WIN32
if (m_hFiles != -1) _findclose(m_hFiles);
m_Valid = ((m_hFiles = _findfirst(FileSpec, &m_FindData)) != -1);
#else
std::string DirectoryName;
if (m_Directory != NULL) closedir(m_Directory);
int i;
for (i = strlen(FileSpec); i >= 0; --i)
if (FileSpec[i] == '/') break;
if (i < 0)
DirectoryName = ".";
else
DirectoryName.assign(FileSpec + 0, FileSpec + i++);
m_Extension = FileSpec + i + 1;
m_Valid = ((m_Directory = opendir(DirectoryName.c_str())) != NULL);
if (! m_Valid)
return (* this);
next();
#endif
return (* this);
}
inline bool search_iterator::end() const {
return false;
}
inline search_iterator & search_iterator::next() {
#if defined WIN32
m_Valid = (_findnext(m_hFiles, &m_FindData) != -1);
#else
bool Found = false;
while (! Found) {
m_Valid = ((m_DirectoryEntry = readdir(m_Directory)) != NULL);
if (m_Valid) {
std::string FileName = m_DirectoryEntry->d_name;
if (FileName[0] == '.')
Found = false;
else if (FileName.size() <= m_Extension.size())
Found = false;
else if (std::equal(m_Extension.rbegin(), m_Extension.rend(), FileName.rbegin()))
Found = true;
}
else
break;
}
#endif
return (* this);
}
inline std::string search_iterator::Name() const {
#if defined WIN32
return (m_FindData.name);
#else
return (m_DirectoryEntry->d_name);
#endif
}
} // namespace io_facilities

View File

@@ -0,0 +1,16 @@
#pragma once
namespace mstatic_assert {
template <bool> class compile_time_error;
template <> class compile_time_error<true> { };
}
#define mstatic_assert(expr) { mstatic_assert::compile_time_error<((expr) != 0)> ERROR_STATIC_ASSERT; (void) ERROR_STATIC_ASSERT; }
#define mstatic_assert_msg(expr, msg) { mstatic_assert::compile_time_error<((expr) != 0)> ERROR_##msg; (void) ERROR_##msg; }

8
JGE/src/zipFS/stdafx.cpp Normal file
View File

@@ -0,0 +1,8 @@
// stdafx.cpp : source file that includes just the standard includes
// zfs.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information
#include "stdafx.h"
// TODO: reference any additional headers you need in STDAFX.H
// and not in this file

21
JGE/src/zipFS/stdafx.h Normal file
View File

@@ -0,0 +1,21 @@
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#pragma once
// Standard headers
#include <algorithm>
#include <cassert>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <map>
#include <string>
#include <vector>
//#include "stdint.h"
#include <stdint.h>

View File

@@ -0,0 +1,77 @@
#ifndef _ZIPFS_STDINT_H_
#define _ZIPFS_STDINT_H_
#include "static_assert.h"
#if defined _MSC_VER
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef signed short int16_t;
typedef unsigned short uint16_t;
typedef signed int int32_t;
typedef unsigned int uint32_t;
typedef signed __int64 int64_t;
typedef unsigned __int64 uint64_t;
typedef signed char int_least8_t;
typedef unsigned char uint_least8_t;
typedef signed short int_least16_t;
typedef unsigned short uint_least16_t;
typedef signed int int_least32_t;
typedef unsigned int uint_least32_t;
typedef signed __int64 int_least64_t;
typedef unsigned __int64 uint_least64_t;
#elif defined UNIX
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef signed short int16_t;
typedef unsigned short uint16_t;
typedef signed int int32_t;
typedef unsigned int uint32_t;
typedef signed long long int64_t;
typedef unsigned long long uint64_t;
typedef signed char int_least8_t;
typedef unsigned char uint_least8_t;
typedef signed short int_least16_t;
typedef unsigned short uint_least16_t;
typedef signed int int_least32_t;
typedef unsigned int uint_least32_t;
typedef signed long long int_least64_t;
typedef unsigned long long uint_least64_t;
#endif
inline void __CheckSizedTypes()
{
// one byte must be exactly 8 bits
//static_assert(CHAR_BIT == 8);
mstatic_assert(sizeof(int8_t) == 1);
mstatic_assert(sizeof(uint8_t) == 1);
mstatic_assert(sizeof(int16_t) == 2);
mstatic_assert(sizeof(uint16_t) == 2);
mstatic_assert(sizeof(int32_t) == 4);
mstatic_assert(sizeof(uint32_t) == 4);
mstatic_assert(sizeof(int64_t) == 8);
mstatic_assert(sizeof(uint64_t) == 8);
mstatic_assert(sizeof(int_least8_t) >= 1);
mstatic_assert(sizeof(uint_least8_t) >= 1);
mstatic_assert(sizeof(int_least16_t) >= 2);
mstatic_assert(sizeof(uint_least16_t) >= 2);
mstatic_assert(sizeof(int_least32_t) >= 4);
mstatic_assert(sizeof(uint_least32_t) >= 4);
mstatic_assert(sizeof(int_least64_t) >= 8);
mstatic_assert(sizeof(uint_least64_t) >= 8);
}
#endif

44
JGE/src/zipFS/zfs.cpp Normal file
View File

@@ -0,0 +1,44 @@
// ZFS.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
// ZFS headers
#include "zfsystem.h"
void DoSomething(std::istream & File)
{
// Output the file via cout (note: rdbuf() method is a std C++ method, not zfs specific)
std::cout << File.rdbuf() << std::endl;
}
int main(int argc, char * argv[])
{
using namespace std;
using zip_file_system::filesystem;
using zip_file_system::izfstream;
// Create and initialize the Zip File System (basepath, file_extension, makedefault)
// and output the its status via cout
filesystem FileSystem("base_data", "cpk", true);
cout << FileSystem << endl;
// Try to open a zipped file (Careful! The openmode is always 'ios::in | ios::binary'.)
izfstream File("testfile.txt");
if (! File)
cout << "ERROR: Cannot open file!" << endl;
// Call some function expecting an istream object
DoSomething(File);
// The End.
cout << "\nPress ENTER to continue." << endl;
cin.get();
}

21
JGE/src/zipFS/zfs.sln Normal file
View File

@@ -0,0 +1,21 @@
Microsoft Visual Studio Solution File, Format Version 8.00
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zfs", "zfs.vcproj", "{54F414A2-0634-467B-95D4-35E8D171D2CA}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfiguration) = preSolution
Debug = Debug
Release = Release
EndGlobalSection
GlobalSection(ProjectConfiguration) = postSolution
{54F414A2-0634-467B-95D4-35E8D171D2CA}.Debug.ActiveCfg = Debug|Win32
{54F414A2-0634-467B-95D4-35E8D171D2CA}.Debug.Build.0 = Debug|Win32
{54F414A2-0634-467B-95D4-35E8D171D2CA}.Release.ActiveCfg = Release|Win32
{54F414A2-0634-467B-95D4-35E8D171D2CA}.Release.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
EndGlobalSection
GlobalSection(ExtensibilityAddIns) = postSolution
EndGlobalSection
EndGlobal

175
JGE/src/zipFS/zfs.vcproj Normal file
View File

@@ -0,0 +1,175 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="zfs"
ProjectGUID="{54F414A2-0634-467B-95D4-35E8D171D2CA}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="Debug"
IntermediateDirectory="Debug"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="5"
UsePrecompiledHeader="3"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)/zfs.exe"
LinkIncremental="2"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/zfs.pdb"
SubSystem="1"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="Release"
IntermediateDirectory="Release"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="4"
UsePrecompiledHeader="3"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)/zfs.exe"
LinkIncremental="1"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
<File
RelativePath=".\stdafx.cpp">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"/>
</FileConfiguration>
</File>
<File
RelativePath=".\zfs.cpp">
</File>
<File
RelativePath=".\zfsystem.cpp">
</File>
<File
RelativePath=".\ziphdr.cpp">
</File>
<File
RelativePath=".\zstream.cpp">
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
<File
RelativePath=".\fileio.h">
</File>
<File
RelativePath=".\static_assert.h">
</File>
<File
RelativePath=".\stdafx.h">
</File>
<File
RelativePath=".\stdint.h">
</File>
<File
RelativePath=".\zfsystem.h">
</File>
<File
RelativePath=".\ziphdr.h">
</File>
<File
RelativePath=".\zstream.h">
</File>
<File
RelativePath=".\zstream_zlib.h">
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

105
JGE/src/zipFS/zfs.vcxproj Normal file
View File

@@ -0,0 +1,105 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{54F414A2-0634-467B-95D4-35E8D171D2CA}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Debug\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Release\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Release\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
<TargetExt Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.lib</TargetExt>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<AdditionalIncludeDirectories>..\JGE\Dependencies\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/NODEFAULTLIB:LIBCMT /NODEFAULTLIB:MSVCPRTD %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<OutputFile>$(OutDir)zfs.exe</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(OutDir)zfs.pdb</ProgramDatabaseFile>
<SubSystem>Console</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
<AdditionalLibraryDirectories>
</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<OutputFile>$(OutDir)zfs.exe</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="zfs.cpp" />
<ClCompile Include="zfsystem.cpp" />
<ClCompile Include="ziphdr.cpp" />
<ClCompile Include="zstream.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="fileio.h" />
<ClInclude Include="static_assert.h" />
<ClInclude Include="stdafx.h" />
<ClInclude Include="stdint.h" />
<ClInclude Include="zfsystem.h" />
<ClInclude Include="ziphdr.h" />
<ClInclude Include="zstream.h" />
<ClInclude Include="zstream_zlib.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="zfs.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="zfsystem.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ziphdr.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="zstream.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="fileio.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="static_assert.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="stdafx.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="stdint.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="zfsystem.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ziphdr.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="zstream.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="zstream_zlib.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

651
JGE/src/zipFS/zfsystem.cpp Normal file
View File

@@ -0,0 +1,651 @@
//Important: This file has been modified in order to be integrated in to JGE++
//
// zfsystem.cpp: implementation of the zip file system classes.
//
// Copyright (C) 2004 Tanguy Fautré.
// For conditions of distribution and use,
// see copyright notice in zfsystem.h
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "zfsystem.h"
#include "fileio.h" // I/O facilities
#if defined (WIN32)
#include <sys/types.h>
#endif
#include <sys/stat.h>
namespace zip_file_system {
using namespace std;
//////////////////////////////////////////////////////////////////////
// Static variables initialization
//////////////////////////////////////////////////////////////////////
filesystem * izfstream::pDefaultFS = NULL;
string filesystem::CurrentZipName = "";
ifstream filesystem::CurrentZipFile;
filesystem * filesystem::pCurrentFS = NULL;
static const int STORED = 0;
static const int DEFLATED = 8;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
filesystem::filesystem(const char * BasePath, const char * FileExt, bool DefaultFS)
: m_BasePath(BasePath), m_FileExt(FileExt)
{
using io_facilities::search_iterator;
// Init m_BasePath and be sure the base path finish with a '/' or a '\'
if (! m_BasePath.empty()) {
string::iterator c = --(m_BasePath.end());
if ((*c != '/') && (*c != '\\'))
m_BasePath += '/';
}
// Search all *.zip files (or whatever the ZipExt specify as the file extension)
vector<string> ZipFiles;
for (search_iterator ZSrch = (m_BasePath + "*." + m_FileExt).c_str(); ZSrch != ZSrch.end(); ++ZSrch)
ZipFiles.push_back(ZSrch.Name());
// Open each zip files that have been found, in alphabetic order
sort(ZipFiles.begin(), ZipFiles.end());
for (vector<string>::const_iterator ZipIt = ZipFiles.begin(); ZipIt != ZipFiles.end(); ++ZipIt)
InsertZip(ZipIt->c_str(), ZipIt - ZipFiles.begin());
// Should we make this the default File System for ifile?
if (DefaultFS)
MakeDefault();
}
//////////////////////////////////////////////////////////////////////
// File System Member Functions
//////////////////////////////////////////////////////////////////////
void filesystem::Open(izfstream & File, const char * Filename)
{
// Close the file if it was opened;
File.close();
File.setFS(this);
// Generate the path and see if the file is zipped or not
string FullPath = m_BasePath + Filename;
// File is not zipped
if (FileNotZipped(FullPath.c_str())) {
// Link the izfile object with an opened filebuf
filebuf * FileBuf = new filebuf;
FileBuf->open(FullPath.c_str(), ios::binary | ios::in);
if (FileBuf->is_open()) {
delete File.rdbuf(FileBuf);
File.clear(ios::goodbit);
File.m_FilePath = Filename;
File.m_FullFilePath = FullPath;
File.m_Zipped = false;
}
// File is maybe zipped
} else {
file_info FileInfo;
string ZipPath;
// Check whether the file is zipped, whether the file is a directory and try to open.
if (FindFile(Filename, &FileInfo) && (! FileInfo.m_Directory) && (! ((ZipPath = FindZip(FileInfo.m_PackID)).empty()))) {
// Get the position of the compressed data
if (CurrentZipName.size())
{
if ((pCurrentFS!= this) || (CurrentZipName.compare(ZipPath) != 0))
{
CurrentZipFile.close();
CurrentZipName = "";
pCurrentFS = NULL;
}
}
if (!CurrentZipName.size())
{
CurrentZipName = ZipPath;
string zipName = m_BasePath + CurrentZipName;
CurrentZipFile.open(zipName.c_str(), ios::binary);
pCurrentFS = this;
}
if (!CurrentZipFile) {
CurrentZipName = "";
pCurrentFS = NULL;
return;
}
streamoff DataPos = SkipLFHdr(CurrentZipFile, streamoff(FileInfo.m_Offset));
if (DataPos != streamoff(-1)) {
string zipName = m_BasePath + CurrentZipName;
// Open the file at the right position
((izstream &) File).open(
zipName.c_str(),
streamoff(DataPos),
streamoff(FileInfo.m_CompSize),
FileInfo.m_CompMethod
);
if (File) {
File.m_FilePath = Filename;
File.m_FullFilePath = FullPath;
File.m_Zipped = true;
File.m_UncompSize = FileInfo.m_Size;
File.m_CompSize = FileInfo.m_CompSize;
File.m_Offset = FileInfo.m_Offset;
}
}
}
}
}
bool filesystem::DirExists(const std::string & folderName)
{
//check real folder
string FullPath = m_BasePath + folderName;
#if defined (WIN32)
struct _stat statBuffer;
if ((_stat(FullPath.c_str(), &statBuffer) >= 0 && // make sure it exists
statBuffer.st_mode & S_IFDIR)) // and it's not a file
return true;
#else
struct stat st;
if (stat(FullPath.c_str(), &st) == 0)
return true;
#endif
//Check in zip
file_info FileInfo;
// Check whether the file is zipped, whether the file is a directory and try to open.
if (FindFile(folderName.c_str(), &FileInfo) && (FileInfo.m_Directory))
return true;
//Neither in real folder nor in zip
return false;
}
// Note: this doesn't scan the folders outside of the zip...should we add that here ?
std::vector<std::string>& filesystem::scanfolder(const std::string& folderName, std::vector<std::string>& results)
{
filemap_const_iterator folderPos = m_Files.find(folderName);
if (folderPos == m_Files.end())
return results;
filemap_const_iterator It = folderPos;
string folderNameLC = folderName;
std::transform(folderNameLC.begin(), folderNameLC.end(), folderNameLC.begin(), ::tolower);
size_t length = folderNameLC.length();
while(++It != m_Files.end())
{
string currentFile = (* It).first;
string currentFileLC = currentFile;
std::transform(currentFileLC.begin(), currentFileLC.end(), currentFileLC.begin(), ::tolower);
if (currentFileLC.find(folderNameLC) == 0)
{
string relativePath = currentFile.substr(length);
size_t pos = relativePath.find_first_of("/\\");
//Only add direct children, no recursive browse
if (pos == string::npos || pos == (relativePath.length() - 1))
results.push_back(relativePath);
}
else
{
break;
//We know other files will not belong to that folder because of the order of the map
}
}
return results;
}
//////////////////////////////////////////////////////////////////////
// File System Protected Member Functions
//////////////////////////////////////////////////////////////////////
bool filesystem::FileNotZipped(const char * FilePath) const
{
//return io_facilities::search_iterator(FilePath);
// follow new search_iterator implementation
std::ifstream File(FilePath);
if (! File)
return false;
return true;
}
bool filesystem::FindFile(const char * Filename, file_info * FileInfo) const
{
filemap_const_iterator It = m_Files.find(Filename);
if (It == m_Files.end())
return false; // File not found
* FileInfo = (* It).second;
return true;
}
const string & filesystem::FindZip(size_t PackID) const
{
static const string EmptyString;
zipmap_const_iterator It = m_Zips.find(PackID);
if (It == m_Zips.end())
return EmptyString; // PackID not valid
return (* It).second.m_Filename;
}
void filesystem::InsertZip(const char * Filename, const size_t PackID)
{
zipfile_info ZipInfo;
// Get full path to the zip file and prepare ZipInfo
ZipInfo.m_Filename = Filename;
string ZipPath = m_BasePath + Filename;
// Open zip
ifstream File(ZipPath.c_str(), ios::binary);
if (! File)
return;
// Find the start of the central directory
if (! File.seekg(CentralDir(File))) return;
// Check every headers within the zip file
file_header FileHdr;
while ((NextHeader(File) == FILE) && (FileHdr.ReadHeader(File))) {
// Include files into Files map
const char * Name = &(* FileHdr.m_Filename.begin());
const unsigned short i = FileHdr.m_FilenameSize - 1;
if (FileHdr.m_FilenameSize != 0) {
m_Files[Name] = file_info(
PackID, // Package ID
FileHdr.m_RelOffset, // "Local File" header offset position
FileHdr.m_UncompSize, // File Size
FileHdr.m_CompSize, // Compressed File Size
FileHdr.m_CompMethod, // Compression Method;
((Name[i] == '/') || (Name[i] == '\\')) // Is a directory?
);
++(ZipInfo.m_NbEntries);
ZipInfo.m_FilesSize += FileHdr.m_UncompSize;
ZipInfo.m_FilesCompSize += FileHdr.m_CompSize;
}
}
File.close();
// Add zip file to Zips data base (only if not empty)
if (ZipInfo.m_NbEntries != 0)
m_Zips[PackID] = ZipInfo;
}
bool filesystem::PreloadZip(const char * Filename, map<string, file_info>& target)
{
zipfile_info ZipInfo;
// Open zip
izfstream File;
File.open(Filename, this);
if (! File)
return false;
// Find the start of the central directory
if (File.Zipped())
{
streamoff realBeginOfFile = SkipLFHdr(CurrentZipFile, File.getOffset());
if (! CurrentZipFile.seekg(CentralDirZipped(CurrentZipFile, realBeginOfFile, File.getCompSize())))
return false;
// Check every headers within the zip file
file_header FileHdr;
while ((NextHeader(CurrentZipFile) == FILE) && (FileHdr.ReadHeader(CurrentZipFile))) {
// Include files into Files map
const char * Name = &(* FileHdr.m_Filename.begin());
const unsigned short i = FileHdr.m_FilenameSize - 1;
if (FileHdr.m_FilenameSize != 0) {
// The zip in zip method only supports stored Zips because of JFileSystem limitations
if ((FileHdr.m_UncompSize != FileHdr.m_CompSize) || FileHdr.m_CompMethod != STORED)
continue;
target[Name] = file_info(
1, // Package ID
realBeginOfFile + FileHdr.m_RelOffset, // "Local File" header offset position
FileHdr.m_UncompSize, // File Size
FileHdr.m_CompSize, // Compressed File Size
FileHdr.m_CompMethod, // Compression Method;
((Name[i] == '/') || (Name[i] == '\\')) // Is a directory?
);
}
}
File.close();
return (target.size() ? true : false);
}
else
{
if (! File.seekg(CentralDir(File)))
return false;
// Check every headers within the zip file
file_header FileHdr;
while ((NextHeader(File) == FILE) && (FileHdr.ReadHeader(File))) {
// Include files into Files map
const char * Name = &(* FileHdr.m_Filename.begin());
const unsigned short i = FileHdr.m_FilenameSize - 1;
if (FileHdr.m_FilenameSize != 0) {
target[Name] = file_info(
1, // Package ID
FileHdr.m_RelOffset, // "Local File" header offset position
FileHdr.m_UncompSize, // File Size
FileHdr.m_CompSize, // Compressed File Size
FileHdr.m_CompMethod, // Compression Method;
((Name[i] == '/') || (Name[i] == '\\')) // Is a directory?
);
}
}
File.close();
return (target.size() ? true : false);
}
}
//////////////////////////////////////////////////////////////////////
// File System Friend Functions
//////////////////////////////////////////////////////////////////////
ostream & operator << (ostream & Out, const filesystem & FS)
{
size_t NbFiles = 0;
filesystem::zipfile_info AllZipsInfo;
for (filesystem::zipmap_const_iterator It = FS.m_Zips.begin(); It != FS.m_Zips.end(); ++It) {
const filesystem::zipfile_info & ZInfo = (* It).second;
// Print zip filename
Out << setiosflags(ios::left) << setw(32) << "-> \"" + ZInfo.m_Filename + "\"" << resetiosflags(ios::left);
// Print number of entries found in this zip file
Out << " " << setw(5) << ZInfo.m_NbEntries << " files";
// Print the uncompressed size of all included files
Out << " " << setw(7) << ZInfo.m_FilesSize / 1024 << " KB";
// Print the compressed size of all these files
Out << " " << setw(7) << ZInfo.m_FilesCompSize / 1024 << " KB packed" << endl;
++NbFiles;
AllZipsInfo.m_NbEntries += ZInfo.m_NbEntries;
AllZipsInfo.m_FilesSize += ZInfo.m_FilesSize;
AllZipsInfo.m_FilesCompSize += ZInfo.m_FilesCompSize;
}
// Print the general info
Out << "\nTotal: ";
Out << NbFiles << " packs ";
Out << AllZipsInfo.m_NbEntries << " files ";
Out << float(AllZipsInfo.m_FilesSize) / (1024 * 1024) << " MB ";
Out << float(AllZipsInfo.m_FilesCompSize) / (1024 * 1024) << " MB packed." << endl;
return Out;
}
//////////////////////////////////////////////////////////////////////
// "Less Than" Comparaison lt_path_str Member Functions
//////////////////////////////////////////////////////////////////////
bool filesystem::lt_path::operator () (const string & s1, const string & s2) const
{
const char * A = s1.c_str();
const char * B = s2.c_str();
for (size_t i = 0; ; ++i) {
if ((A[i] == '\0') && (B[i] == '\0'))
return false;
// case insensitive and '/' is the same as '\'
if (! (
(A[i] == B[i] + ('a' - 'A')) ||
(A[i] == B[i] - ('a' - 'A')) ||
(A[i] == B[i]) ||
((A[i] == '\\') && (B[i] == '/')) ||
((A[i] == '/') && (B[i] == '\\'))
)) {
if ((A[i] == '\0') || (A[i] < B[i]))
return true;
else
return false;
}
}
}
//////////////////////////////////////////////////////////////////////
// Zip Header Classes Related Member Functions
//////////////////////////////////////////////////////////////////////
streamoff filesystem::CentralDirZipped(std::istream & File, std::streamoff begin, std::size_t size) const
{
using io_facilities::readvar;
std::streamoff eof = begin + size;
// Look for the "end of central dir" header. Start minimum 22 bytes before end.
if (! File.seekg(eof - 22, ios::beg))
return -1;
streamoff EndPos;
streamoff StartPos = File.tellg();
if (StartPos == streamoff(0))
return -1;
if (StartPos <= begin + streamoff(65536))
EndPos = 1;
else
EndPos = StartPos - streamoff(65536);
// Start the scan
do {
unsigned int RawSignature;
if (! readvar(File, RawSignature, 4))
return -1;
eofcd_header Header;
streampos Pos = File.tellg();
// Found a potential "eofcd" header?
if ((RawSignature == ENDOFDIR) && (File.seekg(-4, ios::cur)) && (Header.ReadHeader(File))) {
// Check invariant values (1 disk only)
if ((Header.m_NbDisks == 0) && (0 == Header.m_DirDisk) && (Header.m_LocalEntries == Header.m_TotalEntries)) {
// Check comment ends at eof
if (! File.seekg(eof - 1 , ios::beg))
return -1;
if ((File.tellg() + streamoff(1)) == (Pos + streamoff(Header.m_CommentSize + 22 - 4))) {
// Check the start offset leads to a correct directory/file header;
if (! File.seekg(begin + Header.m_Offset)) return -1;
if (! readvar(File, RawSignature, 4)) return -1;
if (RawSignature == FILE)
return begin + Header.m_Offset;
}
}
}
File.seekg(Pos);
} while ((File.seekg(-5, ios::cur)) && (File.tellg() > EndPos) && (File.tellg() > begin));
return -1;
}
streamoff filesystem::CentralDir(istream & File) const
{
using io_facilities::readvar;
// Look for the "end of central dir" header. Start minimum 22 bytes before end.
if (! File.seekg(-22, ios::end)) return -1;
streamoff EndPos;
streamoff StartPos = File.tellg();
if (StartPos == streamoff(0)) return -1;
if (StartPos <= streamoff(65536))
EndPos = 1;
else
EndPos = StartPos - streamoff(65536);
// Start the scan
do {
unsigned int RawSignature;
if (! readvar(File, RawSignature, 4)) return -1;
eofcd_header Header;
streampos Pos = File.tellg();
// Found a potential "eofcd" header?
if ((RawSignature == ENDOFDIR) && (File.seekg(-4, ios::cur)) && (Header.ReadHeader(File))) {
// Check invariant values (1 disk only)
if ((Header.m_NbDisks == 0) && (0 == Header.m_DirDisk) && (Header.m_LocalEntries == Header.m_TotalEntries)) {
// Check comment ends at eof
if (! File.seekg(-1, ios::end)) return -1;
if ((File.tellg() + streamoff(1)) == (Pos + streamoff(Header.m_CommentSize + 22 - 4))) {
// Check the start offset leads to a correct directory/file header;
if (! File.seekg(Header.m_Offset)) return -1;
if (! readvar(File, RawSignature, 4)) return -1;
if (RawSignature == FILE)
return Header.m_Offset;
}
}
}
File.seekg(Pos);
} while ((File.seekg(-5, ios::cur)) && (File.tellg() > EndPos));
return -1;
}
streamoff filesystem::SkipLFHdr(istream & File, streamoff LFHdrPos)
{
using io_facilities::readvar;
unsigned short NameSize;
unsigned short FieldSize;
unsigned int RawSignature;
// verify it's a local header
if (! File.seekg(LFHdrPos)) return -1;
if (! readvar(File, RawSignature, 4)) return -1;
if (RawSignature != LOCALFILE) return -1;
// Skip and go directly to comment/field size
if (! File.seekg(22, ios::cur)) return -1;
if (! readvar(File, NameSize, 2)) return -1;
if (! readvar(File, FieldSize, 2)) return -1;
// Skip comment and extra field
if (! File.seekg(NameSize + FieldSize, ios::cur)) return -1;
// Now we are at the compressed data position
return (File.tellg());
}
headerid filesystem::NextHeader(istream & File) const
{
using io_facilities::readvar;
unsigned int RawSignature;
if (! readvar(File, RawSignature, 4))
return READERROR;
if (! File.seekg(-4, ios::cur))
return READERROR;
headerid Signature = headerid(RawSignature);
switch (Signature) {
case FILE:
case LOCALFILE:
case ENDOFDIR:
return Signature;
default:
return UNKNOWN;
}
}
} // namespace zip_file_system

288
JGE/src/zipFS/zfsystem.h Normal file
View File

@@ -0,0 +1,288 @@
//Important: This file has been modified in order to be integrated in to JGE++
//
// zfsystem.h: interface for the zip file system classes.
//
//////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2004 Tanguy Fautré.
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
// Tanguy Fautré
// softdev@telenet.be
//
//////////////////////////////////////////////////////////////////////
//
// Zip File System.
// ****************
//
// Current version: 1.00 BETA 2 (16/07/2004)
//
// Comment: -
//
// History: - 1.00 BETA 2 (16/07/2004) - Updated to follow latest version
// of fileio.h
// - 1.00 BETA 1 (21/07/2002) - First public release
//
//////////////////////////////////////////////////////////////////////
#pragma once
#include "stdafx.h"
#include "ziphdr.h" // Zip file header
#include "zstream.h" // Zip Stream
// Zip File System Namespace
namespace zip_file_system {
class filesystem;
// Input Zip File class
class izfstream : public izstream
{
public:
izfstream(filesystem * pFS = pDefaultFS);
izfstream(const char * FilePath, filesystem * pFS = pDefaultFS);
void open(const char * FilePath, filesystem * pFS = pDefaultFS);
void close();
bool is_open() const;
void setFS(filesystem * pFS = pDefaultFS);
bool Zipped() const;
const std::string & FilePath() const;
const std::string & FullFilePath() const;
size_t getUncompSize();
size_t getOffset();
size_t getCompSize();
protected:
friend class filesystem;
// Default File System Pointer (default = NULL)
static filesystem * pDefaultFS;
std::string m_FilePath;
std::string m_FullFilePath;
filesystem * m_pFS;
bool m_Zipped;
size_t m_UncompSize;
size_t m_Offset;
size_t m_CompSize;
};
// Zip File System central class
class filesystem
{
public:
// "local" file info class
class file_info
{
public:
file_info() : m_PackID(0), m_Offset(0), m_Size(0), m_CompSize(0), m_CompMethod(0), m_Directory(true) { }
file_info(size_t PackID, size_t Offset, size_t Size, size_t CompSize, short CompMethod, bool Directory) :
m_PackID(PackID), m_Offset(Offset), m_Size(Size), m_CompSize(CompSize), m_CompMethod(CompMethod), m_Directory(Directory) { }
size_t m_PackID;
size_t m_Offset;
size_t m_Size;
size_t m_CompSize;
short m_CompMethod;
bool m_Directory;
};
filesystem(const char * BasePath = "", const char * FileExt = "zip", bool DefaultFS = true);
~filesystem();
void MakeDefault();
void Open(izfstream & File, const char * Filename);
bool DirExists(const std::string & folderName);
bool PreloadZip(const char * Filename, std::map<std::string, file_info>& target);
static std::string getCurrentZipName();
static filesystem * getCurrentFS();
static std::streamoff SkipLFHdr(std::istream & File, std::streamoff LFHdrPos);
//Fills the vector results with a list of children of the given folder
std::vector<std::string>& scanfolder(const std::string& folderName, std::vector<std::string>& results);
friend std::ostream & operator << (std::ostream & Out, const filesystem & FS);
protected:
// Zip file info class
class zipfile_info
{
public:
zipfile_info() : m_NbEntries(0), m_FilesSize(0), m_FilesCompSize(0) { }
std::string m_Filename;
size_t m_NbEntries;
size_t m_FilesSize;
size_t m_FilesCompSize;
};
// Class for file path string comparaison
struct lt_path
{
bool operator() (const std::string & s1, const std::string & s2) const;
};
// Protected member functions
// Zip file format related functions
std::streamoff CentralDir(std::istream & File) const;
std::streamoff CentralDirZipped(std::istream & File, std::streamoff begin, std::size_t size) const;
headerid NextHeader(std::istream & File) const;
// File/Zip map related functions
bool FileNotZipped(const char * FilePath) const;
bool FindFile(const char * Filename, file_info * FileInfo) const;
const std::string & FindZip(size_t PackID) const;
void InsertZip(const char * Filename, const size_t PackID);
// New type definitions
typedef std::map<size_t, zipfile_info> zipmap;
typedef std::map<size_t, zipfile_info>::iterator zipmap_iterator;
typedef std::map<size_t, zipfile_info>::const_iterator zipmap_const_iterator;
typedef std::map<std::string, file_info, lt_path> filemap;
typedef std::map<std::string, file_info, lt_path>::iterator filemap_iterator;
typedef std::map<std::string, file_info, lt_path>::const_iterator filemap_const_iterator;
// Mighty protected member variables
std::string m_BasePath;
std::string m_FileExt;
zipmap m_Zips;
filemap m_Files;
static std::ifstream CurrentZipFile;
static std::string CurrentZipName;
static filesystem * pCurrentFS;
};
//////////////////////////////////////////////////////////////////////
// zip_file_system::izfile Inline Functions
//////////////////////////////////////////////////////////////////////
inline izfstream::izfstream(filesystem * pFS) : m_pFS(pFS) { }
inline izfstream::izfstream(const char * FilePath, filesystem * pFS) : m_pFS(pFS) {
open(FilePath);
}
inline void izfstream::setFS(filesystem * pFS) {
m_pFS = pFS;
}
inline size_t izfstream::getUncompSize()
{
return m_UncompSize;
}
inline size_t izfstream::getOffset()
{
return m_Offset;
}
inline size_t izfstream::getCompSize()
{
return m_CompSize;
}
inline void izfstream::open(const char * FilePath, filesystem * pFS) {
if (pFS)
m_pFS = pFS;
if (m_pFS != NULL)
m_pFS->Open(* this, FilePath);
}
inline void izfstream::close() {
izstream::close();
m_FilePath = m_FullFilePath = "";
m_UncompSize = 0;
}
inline bool izfstream::is_open() const {
return static_cast<zbuffer *>(rdbuf())->is_open();
}
inline bool izfstream::Zipped() const {
return m_Zipped;
}
inline const std::string & izfstream::FilePath() const {
return m_FilePath;
}
inline const std::string & izfstream::FullFilePath() const {
return m_FullFilePath;
}
//////////////////////////////////////////////////////////////////////
// zip_file_system::filesystem Inline Functions
//////////////////////////////////////////////////////////////////////
inline filesystem::~filesystem() {
// Security mesure with izfile::pDefaultFS
if (izfstream::pDefaultFS == this)
izfstream::pDefaultFS = NULL;
if (CurrentZipName.size())
{
CurrentZipFile.close();
CurrentZipName = "";
}
}
inline void filesystem::MakeDefault() {
izfstream::pDefaultFS = this;
}
inline std::string filesystem::getCurrentZipName()
{
return CurrentZipName;
}
inline filesystem * filesystem::getCurrentFS()
{
return pCurrentFS;
}
} // namespace zip_file_system

123
JGE/src/zipFS/ziphdr.cpp Normal file
View File

@@ -0,0 +1,123 @@
// ziphdr.cpp: implementation of the zip header classes.
//
// Copyright (C) 2002 Tanguy Fautré.
// For conditions of distribution and use,
// see copyright notice in ziphdr.h
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "ziphdr.h"
#include "fileio.h" // I/O facilities
namespace zip_file_system {
//////////////////////////////////////////////////////////////////////
// Zip Header Classes Member Functions
//////////////////////////////////////////////////////////////////////
bool local_file_header::ReadHeader(std::istream & File)
{
using io_facilities::readvar;
// quick check about char size
//static_assert(CHAR_BIT == 8);
if (! readvar(File, m_Signature, 4)) return false;
if (! readvar(File, m_VersionExtract, 2)) return false;
if (! readvar(File, m_GeneralFlags, 2)) return false;
if (! readvar(File, m_CompMethod, 2)) return false;
if (! readvar(File, m_Time, 2)) return false;
if (! readvar(File, m_Date, 2)) return false;
if (! readvar(File, m_CRC32, 4)) return false;
if (! readvar(File, m_CompSize, 4)) return false;
if (! readvar(File, m_UncompSize, 4)) return false;
if (! readvar(File, m_FilenameSize, 2)) return false;
if (! readvar(File, m_FieldSize, 2)) return false;
m_Filename.resize(m_FilenameSize + 1);
m_ExtraField.resize(m_FieldSize + 1);
if (! File.read(&(m_Filename[0]), m_FilenameSize)) return false;
if (! File.read(&(m_ExtraField[0]), m_FieldSize)) return false;
m_Filename[m_FilenameSize] = '\0';
m_ExtraField[m_FieldSize] = '\0';
return true;
}
bool file_header::ReadHeader(std::istream & File)
{
using io_facilities::readvar;
if (! readvar(File, m_Signature, 4)) return false;
if (! readvar(File, m_VersionMade, 2)) return false;
if (! readvar(File, m_VersionExtract, 2)) return false;
if (! readvar(File, m_GeneralFlags, 2)) return false;
if (! readvar(File, m_CompMethod, 2)) return false;
if (! readvar(File, m_Time, 2)) return false;
if (! readvar(File, m_Date, 2)) return false;
if (! readvar(File, m_CRC32, 4)) return false;
if (! readvar(File, m_CompSize, 4)) return false;
if (! readvar(File, m_UncompSize, 4)) return false;
if (! readvar(File, m_FilenameSize, 2)) return false;
if (! readvar(File, m_FieldSize, 2)) return false;
if (! readvar(File, m_CommentSize, 2)) return false;
if (! readvar(File, m_DiskNb, 2)) return false;
if (! readvar(File, m_IntAttrib, 2)) return false;
if (! readvar(File, m_ExtAttrib, 4)) return false;
if (! readvar(File, m_RelOffset, 4)) return false;
m_Filename.resize(m_FilenameSize + 1);
m_ExtraField.resize(m_FieldSize + 1);
m_Comment.resize(m_CommentSize + 1);
if (! File.read(&(m_Filename[0]), m_FilenameSize)) return false;
if (! File.read(&(m_ExtraField[0]), m_FieldSize)) return false;
if (! File.read(&(m_Comment[0]), m_CommentSize)) return false;
m_Filename[m_FilenameSize] = '\0';
m_ExtraField[m_FieldSize] = '\0';
m_Comment[m_CommentSize] = '\0';
return true;
}
bool eofcd_header::ReadHeader(std::istream & File)
{
using io_facilities::readvar;
if (! readvar(File, m_Signature, 4)) return false;
if (! readvar(File, m_NbDisks, 2)) return false;
if (! readvar(File, m_DirDisk, 2)) return false;
if (! readvar(File, m_LocalEntries, 2)) return false;
if (! readvar(File, m_TotalEntries, 2)) return false;
if (! readvar(File, m_DirSize, 4)) return false;
if (! readvar(File, m_Offset, 4)) return false;
if (! readvar(File, m_CommentSize, 2)) return false;
m_Comment.resize(m_CommentSize + 1);
if (! File.read(&(m_Comment[0]), m_CommentSize)) return false;
m_Comment[m_CommentSize] = '\0';
return true;
}
} // namespace zip_file_system

143
JGE/src/zipFS/ziphdr.h Normal file
View File

@@ -0,0 +1,143 @@
// zfsystem.h: interface for the zip header classes.
//
//////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2002 Tanguy Fautré.
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
// Tanguy Fautré
// softdev@telenet.be
//
//////////////////////////////////////////////////////////////////////
//
// Zip File Format Headers.
// ***********************
//
// Current version: 1.00 BETA 2 (01/09/2003)
//
// Comment: Based on the ZIP file format specification from Appnote.txt
// from the PKZip Website on July 13, 1998.
// New implementations of the ZIP file format might not work
// correctly (ZIP64 ?).
//
// History: - 1.00 BETA 2 (01/09/2003) - Use stdint.h sized types
// - 1.00 BETA 1 (12/06/2002) - First public release
//
//////////////////////////////////////////////////////////////////////
#pragma once
// Zip File System Namespace
namespace zip_file_system {
// Zip file headers
enum headerid { LOCALFILE = 0x04034b50,
FILE = 0x02014b50,
ENDOFDIR = 0x06054b50,
UNKNOWN,
READERROR
};
// Zip file "local file" header class
struct local_file_header
{
bool ReadHeader(std::istream & File);
static const uint_least32_t m_ConstSign= LOCALFILE;
uint_least32_t m_Signature;
uint_least16_t m_VersionExtract;
uint_least16_t m_GeneralFlags;
uint_least16_t m_CompMethod;
uint_least16_t m_Time;
uint_least16_t m_Date;
uint_least32_t m_CRC32;
uint_least32_t m_CompSize;
uint_least32_t m_UncompSize;
uint_least16_t m_FilenameSize;
uint_least16_t m_FieldSize;
std::vector<char> m_Filename;
std::vector<char> m_ExtraField;
};
// Zip file "file header" header class
struct file_header
{
bool ReadHeader(std::istream & File);
static const headerid m_ConstSign = FILE;
uint_least32_t m_Signature;
uint_least16_t m_VersionMade;
uint_least16_t m_VersionExtract;
uint_least16_t m_GeneralFlags;
uint_least16_t m_CompMethod;
uint_least16_t m_Time;
uint_least16_t m_Date;
uint_least32_t m_CRC32;
uint_least32_t m_CompSize;
uint_least32_t m_UncompSize;
uint_least16_t m_FilenameSize;
uint_least16_t m_FieldSize;
uint_least16_t m_CommentSize;
uint_least16_t m_DiskNb;
uint_least16_t m_IntAttrib;
uint_least32_t m_ExtAttrib;
uint_least32_t m_RelOffset;
std::vector<char> m_Filename;
std::vector<char> m_ExtraField;
std::vector<char> m_Comment;
};
// Zip file "end of central dir" header class
struct eofcd_header
{
bool ReadHeader(std::istream & File);
static const headerid m_ConstSign = ENDOFDIR;
uint_least32_t m_Signature;
uint_least16_t m_NbDisks;
uint_least16_t m_DirDisk;
uint_least16_t m_LocalEntries;
uint_least16_t m_TotalEntries;
uint_least32_t m_DirSize;
uint_least32_t m_Offset;
uint_least16_t m_CommentSize;
std::vector<char> m_Comment;
};
} // namespace zip_file_system

427
JGE/src/zipFS/zstream.cpp Normal file
View File

@@ -0,0 +1,427 @@
// zstream.cpp: implementation of the zstream class.
//
// Copyright (C) 2002 Tanguy Fautré.
// For conditions of distribution and use,
// see copyright notice in zfsystem.h
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "zstream.h"
namespace zip_file_system {
using namespace std;
//////////////////////////////////////////////////////////////////////
// zstream Member Functions
//////////////////////////////////////////////////////////////////////
void izstream::open(const char * Filename, streamoff Offset, streamoff Size, int CompMethod)
{
// Change the buffer if need
if (m_CompMethod == CompMethod) {
if (rdbuf() != NULL)
static_cast<zbuffer *>(rdbuf())->close();
} else
SetCompMethod(CompMethod);
// clear up the file status
clear(ios::goodbit);
// open the buffer
switch (m_CompMethod) {
case STORED:
case DEFLATED:
if (! (static_cast<zbuffer *>(rdbuf())->open(Filename, Offset, Size))) {
setstate(ios::badbit);
SetCompMethod(-1);
}
break;
default:
setstate(ios::badbit);
}
}
zbuffer * izstream::GetRightBuffer(int CompMethod) const
{
switch (CompMethod) {
// stored
case STORED:
return new zbuffer_stored;
// deflated
case DEFLATED:
return new zbuffer_deflated;
// else not supported
default:
return NULL;
}
}
//////////////////////////////////////////////////////////////////////
// zbuffer_stored Member Functions
//////////////////////////////////////////////////////////////////////
zbuffer_stored * zbuffer_stored::open(const char * Filename, streamoff Offset, streamoff Size)
{
// open main compressed file
m_ZipFile.open(Filename, ios::binary);
if (! m_ZipFile)
return NULL;
// adjust file position
if (! m_ZipFile.seekg(Offset, ios::beg))
return NULL;
m_Opened = true;
m_Pos = -1;
m_Size = Size;
return this;
}
zbuffer_stored * zbuffer_stored::close()
{
if (! m_Opened)
return NULL;
else {
m_Opened = false;
m_ZipFile.close();
}
return this;
}
int zbuffer_stored::overflow(int c)
{
return EOF;
}
int zbuffer_stored::underflow()
{
// Buffer Valid?
if (! m_Opened)
return EOF;
// Do we really need to refill it?
if (gptr() < egptr())
return static_cast<unsigned char>(* gptr());
// Refill de buffer.
streamoff ToRead = ((m_Size - m_Pos) < BUFFERSIZE) ? (m_Size - m_Pos) : BUFFERSIZE;
if ((ToRead == 0) || (! m_ZipFile.read(m_Buffer, BUFFERSIZE)))
return EOF;
// Set the real position of the beginning of the buffer.
if (m_Pos == streamoff(-1))
m_Pos = 0;
else
m_Pos += ToRead;
// Reset buffer pointers.
setg( m_Buffer, // beginning of putback area
m_Buffer, // read position
m_Buffer + ToRead); // end of buffer
return static_cast<unsigned char>(m_Buffer[0]);
}
streampos zbuffer_stored::seekoff(streamoff off, ios::seekdir dir, ios::openmode nMode)
{
streamoff WantedPos = 0;
// Find out the wanted position.
switch (dir) {
case ios_base::cur:
WantedPos = m_Pos + streamoff(gptr() - eback()) + off;
break;
case ios_base::beg:
WantedPos = off;
break;
case ios_base::end:
WantedPos = m_Size + off;
break;
default:
assert(false);
}
// Is the position valid?
if ((WantedPos < 0) || (WantedPos > m_Size))
return streambuf::seekoff(off, dir, nMode); // return invalid streamoff
// Is the position already within the buffer?
if ((WantedPos >= m_Pos) && (WantedPos - m_Pos < egptr() - eback())) {
setg(eback(), eback() + (WantedPos - m_Pos), egptr());
return WantedPos;
}
// Fill up the buffer at the right position.
if (! m_ZipFile.seekg(WantedPos, ios::beg))
return streambuf::seekoff(off, dir, nMode);
m_Pos = WantedPos;
streamoff ToRead = ((m_Size - m_Pos) < BUFFERSIZE) ? (m_Size - m_Pos) : BUFFERSIZE;
if (ToRead == 0)
return WantedPos;
if (! m_ZipFile.read(m_Buffer, BUFFERSIZE))
return streambuf::seekoff(off, dir, nMode);
// Set the buffer at the right position
setg(m_Buffer, m_Buffer, m_Buffer + ToRead);
return WantedPos;
}
int zbuffer_stored::sync()
{
return 0;
}
streambuf * zbuffer_stored::setbuf(char * pr, int nLength)
{
return NULL;
}
//////////////////////////////////////////////////////////////////////
// zbuffer_deflated Member Functions
//////////////////////////////////////////////////////////////////////
zbuffer_deflated * zbuffer_deflated::open(const char * Filename, streamoff Offset, streamoff Size)
{
// open main compressed file
m_ZipFile.open(Filename, ios::binary);
if (! m_ZipFile)
return NULL;
// adjust file position
if (! m_ZipFile.seekg(Offset, ios::beg))
return NULL;
// z_stream (NULL) Initialization
m_ZStream.next_in = Z_NULL;
m_ZStream.avail_in = 0;
m_ZStream.total_in = 0;
m_ZStream.next_out = Z_NULL;
m_ZStream.avail_out = 0;
m_ZStream.total_out = 0;
m_ZStream.zalloc = Z_NULL;
m_ZStream.zfree = Z_NULL;
m_ZStream.opaque = Z_NULL;
// inflate routine Initialization: Window Size = -MAX_WBITS tells there are no header
if (inflateInit2(&m_ZStream, -MAX_WBITS) != Z_OK)
return NULL;
m_Opened = true;
m_StreamEnd = false;
m_Pos = 0;
m_CompPos = 0;
m_Size = Size;
return this;
}
zbuffer_deflated * zbuffer_deflated::close()
{
if (! m_Opened)
return NULL;
else {
m_Opened = false;
m_ZipFile.close();
// z_stream unitialization.
if (inflateEnd(&m_ZStream) != Z_OK)
return NULL;
}
return this;
}
int zbuffer_deflated::overflow(int c)
{
return EOF;
}
int zbuffer_deflated::underflow()
{
// Buffer Valid?
if (! m_Opened)
return EOF;
// Do we really need to refill it?
if (gptr() < egptr())
return static_cast<unsigned char>(* gptr());
// Can we refill?
if (m_StreamEnd)
return EOF;
streamoff ToRead;
streamoff OldPos;
bool BufferRefill = false;
// Check input (compressed) buffer status
if ((m_ZStream.avail_in == 0) && (m_CompPos < m_Size )) {
ToRead = ((m_Size - m_CompPos) > BUFFERSIZE) ? BUFFERSIZE : (m_Size - m_CompPos);
m_CompPos += ToRead;
if (! m_ZipFile.read(m_CompBuffer, ToRead))
return EOF;
m_ZStream.next_in = reinterpret_cast<unsigned char *>(m_CompBuffer);
m_ZStream.avail_in = ToRead;
}
// Ajust start read position in output buffer at the "old" end of buffer
ToRead = m_ZStream.total_out % BUFFERSIZE;
OldPos = m_ZStream.total_out;
// Check output (decompressed) buffer status
if (m_ZStream.avail_out == 0) {
BufferRefill = true;
m_ZStream.next_out = reinterpret_cast<unsigned char *>(m_Buffer);
m_ZStream.avail_out = BUFFERSIZE;
}
// Decompress (Inflate)
int Result = inflate(&m_ZStream, Z_SYNC_FLUSH);
// Check decompression result
if (Result == Z_STREAM_END)
m_StreamEnd = true;
else if (Result != Z_OK)
return EOF;
// Set the real position of the beginning of the buffer.
if (m_Pos == streamoff(-1))
m_Pos = 0;
else
if (BufferRefill)
m_Pos += m_ZStream.total_out - OldPos;
// Reset buffer pointers.
setg( m_Buffer, // beginning of putback area
m_Buffer + ToRead, // read position
m_Buffer + ((m_ZStream.total_out - 1) % (BUFFERSIZE)) + 1); // end of buffer
return static_cast<unsigned char>(m_Buffer[ToRead]);
}
streampos zbuffer_deflated::seekoff(std::streamoff off, std::ios::seekdir dir, std::ios::openmode nMode)
{
streamoff WantedPos = 0;
// Find out the wanted position.
switch (dir) {
case ios_base::cur:
WantedPos = m_Pos + streamoff(gptr() - eback()) + off;
break;
case ios_base::beg:
WantedPos = off;
break;
case ios_base::end:
WantedPos = m_Size + off;
break;
default:
assert(false);
}
// Is the position valid?
if ((WantedPos < 0) || (WantedPos > m_Size))
return streambuf::seekoff(off, dir, nMode); // return invalid streamoff
// Is the position already within the buffer?
if ((WantedPos >= m_Pos) && (WantedPos - m_Pos < egptr() - eback())) {
setg(eback(), eback() + (WantedPos - m_Pos), egptr());
return WantedPos;
}
// Found out whether we have to decompress further or if we have to reset the decompression.
if (WantedPos < m_Pos) {
// Reset the decompression.
if (inflateReset(&m_ZStream) != Z_OK)
return streambuf::seekoff(off, dir, nMode);
// z_stream Reset
m_ZStream.next_in = Z_NULL;
m_ZStream.avail_in = 0;
m_ZStream.total_in = 0;
m_ZStream.next_out = Z_NULL;
m_ZStream.avail_out = 0;
m_ZStream.total_out = 0;
}
// call underflow() untill the right position is within the buffer.
while (WantedPos - m_Pos >= egptr() - eback()) {
setg(eback(), egptr(), egptr());
if (underflow() == EOF)
return streambuf::seekoff(off, dir, nMode);
}
// now the position is within the buffer.
setg(eback(), eback() + (WantedPos - m_Pos), egptr());
return WantedPos;
}
int zbuffer_deflated::sync()
{
return 0;
}
streambuf * zbuffer_deflated::setbuf(char * pr, int nLength)
{
return NULL;
}
} // namespace zip_file_system

172
JGE/src/zipFS/zstream.h Normal file
View File

@@ -0,0 +1,172 @@
// zstream.h: interface for the zstream classes.
//
//////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2002 Tanguy Fautré.
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
// Tanguy Fautré
// softdev@telenet.be
//
//////////////////////////////////////////////////////////////////////
//
// Zip (Input) Stream.
// *******************
//
// Current version: 1.00 BETA 4 (02/09/2003)
//
// Comment: izstream currently only supports "stored" and "deflated"
// compression methods.
//
// !!!IMPORTANT!!!
// Modify "zstream_zlib.h" for headers and lib dependencies
// on Zlib (http://www.zlib.org)
//
// History: - 1.00 BETA 4 (02/09/2003) - Made zbuffer constructor protected
// - 1.00 BETA 3 (21/02/2003) - Fixed bugs with seekoff()
// - 1.00 BETA 2 (23/12/2002) - Fixed a bug with izstream
// (Added m_ComMethod(-1) in constructor)
// - 1.00 BETA 1 (29/05/2002) - First public release
//
//////////////////////////////////////////////////////////////////////
#pragma once
#include "zstream_zlib.h" // Zlib dependencies
// Zip File System Namespace
namespace zip_file_system {
// Base buffer class
class zbuffer : public std::streambuf
{
public:
virtual ~zbuffer() { }
virtual zbuffer * open(const char * Filename, std::streamoff Offset, std::streamoff Size) = 0;
virtual zbuffer * close() = 0;
bool is_open() const { return m_Opened; }
protected:
zbuffer() : m_Size(0), m_Opened(false) { }
static const int BUFFERSIZE = 4092;
std::ifstream m_ZipFile;
std::streamoff m_Pos;
std::streamoff m_Size;
char m_Buffer[BUFFERSIZE];
bool m_Opened;
};
// Buffer class for stored compression method.
class zbuffer_stored : public zbuffer
{
public:
virtual ~zbuffer_stored() { }
virtual zbuffer_stored * open(const char * Filename, std::streamoff Offset, std::streamoff Size);
virtual zbuffer_stored * close();
virtual int overflow(int c = EOF);
virtual int underflow();
virtual int sync();
virtual std::streambuf * setbuf(char * pr, int nLength);
virtual std::streampos seekoff(std::streamoff, std::ios::seekdir, std::ios::openmode);
// Default Implementation is enough
// virtual streampos seekpos(streampos, int);
};
// Buffer class for deflated compression method.
class zbuffer_deflated : public zbuffer
{
public:
virtual ~zbuffer_deflated() {
if (m_Opened)
inflateEnd(&m_ZStream);
}
virtual zbuffer_deflated * open(const char * Filename, std::streamoff Offset, std::streamoff Size);
virtual zbuffer_deflated * close();
virtual int overflow(int c = EOF);
virtual int underflow();
virtual int sync();
virtual std::streambuf * setbuf(char * pr, int nLength);
virtual std::streampos seekoff(std::streamoff, std::ios::seekdir, std::ios::openmode);
// Default Implementation is enough
// virtual streampos seekpos(streampos, int);
protected:
z_stream m_ZStream;
std::streamoff m_CompPos;
char m_CompBuffer[BUFFERSIZE];
bool m_StreamEnd;
};
// main istream class for reading zipped files
class izstream : public std::istream
{
public:
izstream() : std::istream(NULL), m_CompMethod(-1) { setstate(std::ios::badbit); }
virtual ~izstream() { delete rdbuf(); }
void open(const char * Filename, std::streamoff Offset, std::streamoff Size, int CompMethod);
void close() { SetCompMethod(-1); }
protected:
static const int STORED = 0;
static const int DEFLATED = 8;
zbuffer * GetRightBuffer(int CompMethod) const;
void SetCompMethod(int CompMethod) {
delete rdbuf(GetRightBuffer(m_CompMethod = CompMethod));
if (rdbuf() == NULL)
setstate(std::ios::badbit);
}
int m_CompMethod;
};
} // namespace zip_file_system;

View File

@@ -0,0 +1,27 @@
//////////////////////////////////////////////////////////////////////
//
// !!! IMPORTANT !!!
//
// You'll need to modify the following library and header paths to
// correctly link with ZLib.
//
//////////////////////////////////////////////////////////////////////
#pragma once
#include <zlib.h>
// Visual C++
/*
#if defined _MSC_VER
#if defined _DEBUG
#pragma comment(lib, "../JGE/Dependencies/lib/zlibd.lib")
#else
#pragma comment(lib, "../JGE/Dependencies/lib/zdll.lib")
#endif
#endif
*/