1
0
Fork 0
mirror of https://github.com/AquariaOSE/Aquaria.git synced 2025-07-03 06:24:32 +00:00

Revert "added partial VFS support - enough to read static data from any source"

This reverts commit fa3e9e7329.
This commit is contained in:
fgenesis 2011-09-15 19:18:53 +02:00
parent fa3e9e7329
commit 56c6833220
56 changed files with 608 additions and 4023 deletions

View file

@ -24,7 +24,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "ScriptedEntity.h"
#include "AutoMap.h"
#include "GridRender.h"
#include <VFSFile.h>
#include "tinyxml.h"
@ -871,7 +870,7 @@ void Continuity::loadTreasureData()
std::string line, gfx;
int num, use;
float sz;
VFSTextStdStreamIn in2("data/treasures.txt");
std::ifstream in2("data/treasures.txt");
while (std::getline(in2, line))
{
std::istringstream is(line);
@ -904,7 +903,7 @@ void Continuity::loadIngredientData()
/*
int num;
VFSTextStreamIn in2("data/ingredientdescriptions.txt");
std::ifstream in2("data/ingredientdescriptions.txt");
while (std::getline(in2, line))
{
IngredientDescription desc;
@ -917,7 +916,7 @@ void Continuity::loadIngredientData()
clearIngredientData();
recipes.clear();
VFSTextStdStreamIn in("data/ingredients.txt");
std::ifstream in("data/ingredients.txt");
bool recipes = false;
while (std::getline(in, line))
@ -1242,7 +1241,7 @@ void Continuity::loadEatBank()
{
eats.clear();
VFSTextStdStreamIn inf("data/eats.txt");
std::ifstream inf("data/eats.txt");
EatData curData;
std::string read;
@ -2182,7 +2181,7 @@ void Continuity::setActivePet(int flag)
void Continuity::loadPetData()
{
petData.clear();
VFSTextStdStreamIn in("data/pets.txt");
std::ifstream in("data/pets.txt");
std::string read;
while (std::getline(in, read))
{
@ -3260,7 +3259,7 @@ void Continuity::reset()
health = maxHealth;
speedTypes.clear();
VFSTextStreamIn inFile("data/speedtypes.txt");
std::ifstream inFile("data/speedtypes.txt");
int n, spd;
while (inFile >> n)
{

View file

@ -172,6 +172,28 @@ DSQ::DSQ(std::string fileSystem) : Core(fileSystem, LR_MAX, APPNAME, PARTICLE_AM
almb = armb = 0;
bar_left = bar_right = bar_up = bar_down = barFade_left = barFade_right = 0;
// do copy stuff
#ifdef BBGE_BUILD_UNIX
std::string fn;
fn = getPreferencesFolder() + "/" + userSettingsFilename;
if (!exists(fn))
Linux_CopyTree(core->adjustFilenameCase(userSettingsFilename).c_str(), core->adjustFilenameCase(fn).c_str());
fn = getUserDataFolder() + "/_mods";
if (!exists(fn))
Linux_CopyTree(core->adjustFilenameCase("_mods").c_str(), core->adjustFilenameCase(fn).c_str());
#endif
#if defined(BBGE_BUILD_UNIX)
std::string p1 = getUserDataFolder();
std::string p2 = getUserDataFolder() + "/save";
mkdir(p1.c_str(), S_IRWXU);
mkdir(p2.c_str(), S_IRWXU);
//debugLogPath = ;
#endif
difficulty = DIFF_NORMAL;
/*
@ -209,6 +231,9 @@ DSQ::DSQ(std::string fileSystem) : Core(fileSystem, LR_MAX, APPNAME, PARTICLE_AM
achievement_box = 0;
#endif
vars = &v;
v.load();
#ifdef AQUARIA_BUILD_CONSOLE
console = 0;
#endif
@ -230,6 +255,25 @@ DSQ::DSQ(std::string fileSystem) : Core(fileSystem, LR_MAX, APPNAME, PARTICLE_AM
for (int i = 0; i < 16; i++)
firstElementOnLayer[i] = 0;
addStateInstance(game = new Game);
addStateInstance(new GameOver);
#ifdef AQUARIA_BUILD_SCENEEDITOR
addStateInstance(new AnimationEditor);
#endif
addStateInstance(new Intro2);
addStateInstance(new BitBlotLogo);
#ifdef AQUARIA_BUILD_SCENEEDITOR
addStateInstance(new ParticleEditor);
#endif
addStateInstance(new Credits);
addStateInstance(new Intro);
addStateInstance(new Nag);
//addStateInstance(new Logo);
//addStateInstance(new SCLogo);
//addStateInstance(new IntroText);
//addStateInstance(new Intro);
//stream = 0;
}
@ -299,7 +343,7 @@ void DSQ::newGame()
void DSQ::loadElementEffects()
{
VFSTextStdStreamIn inFile("data/elementeffects.txt");
std::ifstream inFile("data/elementeffects.txt");
elementEffects.clear();
std::string line;
while (std::getline(inFile, line))
@ -871,55 +915,6 @@ static bool sdlVideoModeOK(const int w, const int h, const int bpp)
void DSQ::init()
{
setupVFS(getenv("AQUARIA_DATA_PATH"));
// FG: TODO: do the moving & copying below with VFS code, and leave the original file system alone!
// do copy stuff
#ifdef BBGE_BUILD_UNIX
std::string fn;
fn = getPreferencesFolder() + "/" + userSettingsFilename;
if (!exists(fn))
Linux_CopyTree(core->adjustFilenameCase(userSettingsFilename).c_str(), core->adjustFilenameCase(fn).c_str());
fn = getUserDataFolder() + "/_mods";
if (!exists(fn))
Linux_CopyTree(core->adjustFilenameCase("_mods").c_str(), core->adjustFilenameCase(fn).c_str());
#endif
#if defined(BBGE_BUILD_UNIX)
std::string p1 = getUserDataFolder();
std::string p2 = getUserDataFolder() + "/save";
mkdir(p1.c_str(), S_IRWXU);
mkdir(p2.c_str(), S_IRWXU);
//debugLogPath = ;
#endif
vars = &v;
v.load();
addStateInstance(game = new Game);
addStateInstance(new GameOver);
#ifdef AQUARIA_BUILD_SCENEEDITOR
addStateInstance(new AnimationEditor);
#endif
addStateInstance(new Intro2);
addStateInstance(new BitBlotLogo);
#ifdef AQUARIA_BUILD_SCENEEDITOR
addStateInstance(new ParticleEditor);
#endif
addStateInstance(new Credits);
addStateInstance(new Intro);
addStateInstance(new Nag);
//addStateInstance(new Logo);
//addStateInstance(new SCLogo);
//addStateInstance(new IntroText);
//addStateInstance(new Intro);
core->settings.runInBackground = true;
weird = 0;
@ -2171,13 +2166,6 @@ void DSQ::loadMods()
{
modEntries.clear();
// force VFS to reload _mods dir
if(ttvfs::VFSDir *vd = vfs.GetDir("_mods"))
{
vd->load();
vfs.Reload();
}
forEachFile(mod.getBaseModPath(), ".xml", loadModsCallback, 0);
selectedMod = 0;
}
@ -3687,7 +3675,7 @@ void DSQ::onPlayVoice()
if (user.audio.subtitles)
{
std::string fn = "scripts/vox/" + sound->lastVoice + ".txt";
VFSTextStdStreamIn inf(fn.c_str());
std::ifstream inf(fn.c_str());
if (inf.is_open())
{
std::string dia;
@ -3780,6 +3768,31 @@ std::string DSQ::getDialogueFilename(const std::string &f)
return "dialogue/" + languagePack + "/" + f + ".txt";
}
void DSQ::jumpToSection(std::ifstream &inFile, const std::string &section)
{
if (section.empty()) return;
std::string file = dsq->getDialogueFilename(dialogueFile);
if (!exists(file))
{
debugLog("Could not find dialogue [" + file + "]");
return;
}
inFile.open(core->adjustFilenameCase(file).c_str());
std::string s;
while (std::getline(inFile, s))
{
if (!s.empty())
{
if (s.find("[")!=std::string::npos && s.find(section) != std::string::npos)
{
return;
}
}
}
debugLog("could not find section [" + section + "]");
}
void DSQ::runGesture(const std::string &line)
{
std::istringstream is(line);

View file

@ -1395,6 +1395,8 @@ public:
void takeScreenshot();
void takeScreenshotKey();
void jumpToSection(std::ifstream &inFile, const std::string &section);
PathFinding pathFinding;
void runGesture(const std::string &line);
void generateCollisionMask(RenderObject *r);

View file

@ -31,7 +31,7 @@ Emote::Emote()
void Emote::load(const std::string &file)
{
emotes.clear();
VFSTextStdStreamIn in(file.c_str());
std::ifstream in(file.c_str());
std::string line;
while (std::getline(in, line))

View file

@ -39,7 +39,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "StatsAndAchievements.h"
#include "ToolTip.h"
#include <VFSFile.h>
std::vector<std::string> allowedMaps;
@ -2517,7 +2516,7 @@ void Game::loadEntityTypeList()
// and group list!
{
entityTypeList.clear();
VFSTextStdStreamIn in("scripts/entities/entities.txt");
std::ifstream in("scripts/entities/entities.txt");
std::string line;
if(!in)
{
@ -2550,7 +2549,7 @@ void Game::loadEntityTypeList()
fn = dsq->mod.getPath() + "entitygroups.txt";
}
VFSTextStdStreamIn in2(fn.c_str());
std::ifstream in2(fn.c_str());
int curGroup=0;
while (std::getline(in2, line))
@ -5404,7 +5403,7 @@ void Game::findMaxCameraValues()
void Game::setWarpAreaSceneName(WarpArea &warpArea)
{
VFSTextStdStreamIn in("data/warpAreas.txt");
std::ifstream in("data/warpAreas.txt");
std::string color, area1, dir1, area2, dir2;
std::string line;
while (std::getline(in, line))
@ -7934,9 +7933,9 @@ void Game::onFlipTest()
void appendFileToString(std::string &string, const std::string &file)
{
VFSTextStdStreamIn inf(file.c_str());
std::ifstream inf(file.c_str());
if (inf)
if (inf.is_open())
{
while (!inf.eof())
{
@ -10946,7 +10945,7 @@ void Game::loadElementTemplates(std::string pack)
tileCache.clean();
}
VFSTextStdStreamIn in(fn.c_str());
std::ifstream in(fn.c_str());
std::string line;
while (std::getline(in, line))
{

View file

@ -24,13 +24,12 @@ GameplayVariables *vars = 0;
void GameplayVariables::load()
{
VFSTextStreamIn inFile("data/variables.txt");
std::ifstream inFile("data/variables.txt");
if(!inFile)
{
core->messageBox("error", "Variables data not found! Aborting...");
exit(1);
}
std::string s;
inFile >> s >> maxSlowSwimSpeed;
inFile >> s >> maxSwimSpeed;

View file

@ -41,10 +41,10 @@ static void StartAQConfig()
{
#if defined(BBGE_BUILD_WINDOWS)
#if defined(AQUARIA_DEMO) || defined(AQUARIA_FULL)
if (!exists("ran", false, true))
if (!exists("ran", false))
{
MakeRan();
if(exists("aqconfig.exe", false, true))
if(exists("aqconfig.exe", false))
{
ShellExecute(NULL, "open", "aqconfig.exe", NULL, NULL, SW_SHOWNORMAL);
exit(0);
@ -58,7 +58,7 @@ static void StartAQConfig()
static void CheckConfig(void)
{
#ifdef BBGE_BUILD_WINDOWS
bool hasCfg = exists("usersettings.xml", false, true);
bool hasCfg = exists("usersettings.xml", false);
if(!hasCfg)
StartAQConfig();
#endif

View file

@ -529,7 +529,7 @@ luaFunc(indexWarnGlobal)
std::ostringstream os;
os << "WARNING: " << ar.short_src << ":" << ar.currentline
<< ": script tried to get/call undefined global variable "
<< varname;
<< lua_tostring(L, -2);
errorLog(os.str());
}
@ -614,19 +614,7 @@ luaFunc(dofile_caseinsensitive)
// This is Lua's dofile(), with some tweaks. --ryan.
std::string fname(core->adjustFilenameCase(luaL_checkstring(L, 1)));
int n = lua_gettop(L);
int result = -1;
ttvfs::VFSFile *vf = core->vfs.GetFile(fname.c_str());
if(vf)
{
const char *buf = (const char*)vf->getBuf();
result = luaL_loadbuffer(L, buf, vf->size(), fname.c_str());
vf->dropBuf(true);
}
if(result)
lua_error(L);
if (luaL_loadfile(L, fname.c_str()) != 0) lua_error(L);
lua_call(L, 0, LUA_MULTRET);
return lua_gettop(L) - n;
}
@ -8953,20 +8941,11 @@ Script *ScriptInterface::openScript(const std::string &file)
lua_getglobal(baseState, "v");
// Load the file itself. This leaves the Lua chunk on the stack.
int result = -1;
ttvfs::VFSFile *vf = core->vfs.GetFile(realFile.c_str());
if(vf)
{
const char *buf = (const char*)vf->getBuf();
result = luaL_loadbuffer(baseState, buf, vf->size(), realFile.c_str());
vf->dropBuf(true);
}
int result = luaL_loadfile(baseState, realFile.c_str());
if (result != 0)
{
const char *msg = lua_tostring(baseState, -1);
debugLog("Error loading script [" + realFile + "]: " + (msg ? msg : "unk error")); // loading from buffer does not push a string on the stack
//lua_pop(baseState, 2);
debugLog("Error loading script [" + realFile + "]: " + lua_tostring(baseState, -1));
lua_pop(baseState, 2);
return NULL;
}

View file

@ -25,8 +25,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "../BBGE/MathFunctions.h"
#include <VFSFile.h>
Shot::Shots Shot::shots;
Shot::ShotBank Shot::shotBank;
@ -66,7 +64,7 @@ ShotData::ShotData()
ignoreShield = false;
}
template <typename T> void readEquals2(T &in)
void readEquals2(std::ifstream &in)
{
std::string temp;
in >> temp;
@ -95,7 +93,7 @@ void ShotData::bankLoad(const std::string &file, const std::string &path)
}
debugLog(usef);
VFSTextStreamIn inf(usef.c_str());
std::ifstream inf(usef.c_str());
std::string token;
while (inf >> token)
{

View file

@ -22,7 +22,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "Game.h"
#include "Avatar.h"
#include "StatsAndAchievements.h"
#include <VFSFile.h>
#ifndef ARRAYSIZE
#define ARRAYSIZE(x) (sizeof (x) / sizeof ((x)[0]))
@ -172,50 +171,46 @@ void StatsAndAchievements::RunFrame()
requestedStats = true;
const size_t max_achievements = ARRAYSIZE(g_rgAchievements);
FILE *io = NULL;
char *achtxt = "";
VFSTextStdStreamIn in("data/achievements.txt");
std::string line;
// HACK: prepare fields in case data are missing
for(int i = 0; i < max_achievements; ++i)
// Get generic achievement data...
io = fopen("data/achievements.txt", "r");
char line[1024];
for (size_t i = 0; i < max_achievements; i++)
{
g_rgAchievements[i].iconImage = 0;
g_rgAchievements[i].name[sizeof (g_rgAchievements[i].name) - 1] = '\0'; // just in case.
g_rgAchievements[i].desc[sizeof (g_rgAchievements[i].desc) - 1] = '\0';
snprintf(g_rgAchievements[i].name, sizeof(g_rgAchievements[i].name), "Achievement #%d", i);
snprintf(g_rgAchievements[i].desc, sizeof(g_rgAchievements[i].desc), "[Description of Achievement #%d is missing!]", i);
}
// read 2 lines per achievement
int x = 0;
int ach = 0;
while(std::getline(in, line))
if (!io || (fgets(line, sizeof (line), io) == NULL))
snprintf(line, sizeof (line), "Achievement #%d", (int) i);
else
{
for (char *ptr = const_cast<char*>(line.c_str() + line.length()) - 1; (ptr >= line) && ((*ptr == '\r') || (*ptr == '\n')); ptr--)
for (char *ptr = (line + strlen(line)) - 1; (ptr >= line) && ((*ptr == '\r') || (*ptr == '\n')); ptr--)
*ptr = '\0';
}
line[sizeof (g_rgAchievements[i].name) - 1] = '\0'; // just in case.
strcpy(g_rgAchievements[i].name, line);
switch(x)
if (!io || (fgets(line, sizeof (line), io) == NULL))
snprintf(line, sizeof (line), "[Description of Achievement #%d is missing!]", (int) i);
else
{
case 0:
strncpy(g_rgAchievements[ach].name, line.c_str(), sizeof(g_rgAchievements[ach].name) - 1);
++x;
break;
for (char *ptr = (line + strlen(line)) - 1; (ptr >= line) && ((*ptr == '\r') || (*ptr == '\n')); ptr--)
*ptr = '\0';
}
line[sizeof (g_rgAchievements[i].desc) - 1] = '\0'; // just in case.
strcpy(g_rgAchievements[i].desc, line);
case 1:
strncpy(g_rgAchievements[ach].desc, line.c_str(), sizeof(g_rgAchievements[ach].desc) - 1);
x = 0;
++ach;
}
// unsupported at the moment.
g_rgAchievements[i].iconImage = 0;
}
if (io != NULL)
fclose(io);
// See what this specific player has achieved...
// FG: TODO: use VFS here!
unsigned char *buf = new unsigned char[max_achievements];
size_t br = 0;
const std::string fname(core->getUserDataFolder() + "/achievements.bin");
FILE *io = fopen(fname.c_str(), "rb");
io = fopen(fname.c_str(), "rb");
if (io == NULL)
statsValid = true; // nothing to report.
else

View file

@ -29,7 +29,7 @@ void StringBank::load(const std::string &file)
//debugLog("StringBank::load("+file+")");
stringMap.clear();
VFSTextStdStreamIn in(file.c_str());
std::ifstream in(file.c_str());
std::string line;
int idx;

View file

@ -61,7 +61,7 @@ void SubtitlePlayer::go(const std::string &subs)
}
}
VFSTextStdStreamIn in(f.c_str());
std::ifstream in(f.c_str());
std::string line;
while (std::getline(in, line))
{

View file

@ -246,7 +246,7 @@ void WorldMap::load(const std::string &file)
std::string line;
VFSTextStdStreamIn in(file.c_str());
std::ifstream in(file.c_str());
while (std::getline(in, line))
{
@ -261,7 +261,6 @@ void WorldMap::load(const std::string &file)
void WorldMap::save(const std::string &file)
{
// FG: TODO: use VFS here!
std::ofstream out(file.c_str());
for (int i = 0; i < worldMapTiles.size(); i++)

View file

@ -20,7 +20,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "Base.h"
#include "Core.h"
#include "VFSDir.h"
#ifdef BBGE_BUILD_WINDOWS
#include <shellapi.h>
@ -273,16 +272,17 @@ std::string upperCase(const std::string &s1)
return ret;
}
bool exists(const std::string &f, bool makeFatal /* = false */, bool skipVFS /* = false */)
bool exists(const std::string &f, bool makeFatal)
{
if (f.empty())
return false;
if(!skipVFS)
/*
if (!PHYSFS_exists(f.c_str()))
{
if(core->vfs.GetFile(core->adjustFilenameCase(f).c_str()))
return true;
}
*/
/*
std::ostringstream os;
os << "checking to see if [" << f << "] exists";
debugLog(os.str());
*/
FILE *file = fopen(core->adjustFilenameCase(f).c_str(), "rb");
if (!file)
@ -295,6 +295,7 @@ bool exists(const std::string &f, bool makeFatal /* = false */, bool skipVFS /*
return false;
}
fclose(file);
//}
return true;
}
@ -447,20 +448,107 @@ void debugLog(const std::string &s)
// delete[] when no longer needed.
char *readFile(std::string path, unsigned long *size_ret)
{
ttvfs::VFSFile *vf = core->vfs.GetFile(path.c_str());
if(!vf)
FILE *f = fopen(path.c_str(), "rb");
if (!f)
return NULL;
vf->getBuf(); // force size calc early
// we can never know how the memory was allocated;
// because the buffer is expected to be deleted with delete[],
// it has to be explicitly copied to memory allocated with new[].
unsigned long s = vf->size();
char *buf = new char[s + 1];
memcpy(buf, vf->getBuf(), s + 1);
core->addVFSFileForDrop(vf);
long fileSize;
if (fseek(f, 0, SEEK_END) != 0
|| (fileSize = ftell(f)) < 0
|| fseek(f, 0, SEEK_SET) != 0)
{
debugLog(path + ": Failed to get file size");
fclose(f);
return NULL;
}
char *buffer = new char[fileSize + 1];
if (!buffer)
{
std::ostringstream os;
os << path << ": Not enough memory for file ("
<< (fileSize+1) << " bytes)";
debugLog(os.str());
fclose(f);
return NULL;
}
long bytesRead = fread(buffer, 1, fileSize, f);
if (bytesRead != fileSize)
{
std::ostringstream os;
os << path << ": Failed to read file (only got "
<< bytesRead << " of " << fileSize << " bytes)";
debugLog(os.str());
fclose(f);
return NULL;
}
fclose(f);
if (size_ret)
*size_ret = s;
return buf;
*size_ret = fileSize;
buffer[fileSize] = 0;
return buffer;
}
/*
void pForEachFile(std::string path, std::string type, void callback(const std::string &filename, int param), int param)
{
char **rc = PHYSFS_enumerateFiles(path.c_str());
char **i;
for (i = rc; *i != NULL; i++)
{
std::string s(*i);
int p=0;
if ((p=s.find('.'))!=std::string::npos)
{
std::string ext = s.susbtr(p, s.getLength2D());
if (ext == type)
{
callback(fielnameafhghaha
}
}
}
PHYSFS_freeList(rc);
}
*/
void doSingleFile(const std::string &path, const std::string &type, std::string filename, void callback(const std::string &filename, int param), int param)
{
if (filename.size()>4)
{
std::string search = filename;
stringToLower(search);
std::string filetype = filename.substr(search.size()-4, search.size());
//stringToUpper(filetype);
//debugLog("comparing: " + filetype + " and: " + type);
//if (filetype==type)
debugLog("checking:" + search + " for type:" + type);
if (search.find(type)!=std::string::npos)
{
debugLog("callback");
callback(path+filename, param);
}
else
{
debugLog("not the same");
}
}
}
std::string stripEndlineForUnix(const std::string &in)
{
std::string out;
for (int i = 0; i < in.size(); i++)
{
if (int(in[i]) != 13)
{
out+= in[i];
}
}
return out;
}
void forEachFile(std::string path, std::string type, void callback(const std::string &filename, intptr_t param), intptr_t param)
@ -472,29 +560,167 @@ void forEachFile(std::string path, std::string type, void callback(const std::st
//HACK: MAC:
debugLog("forEachFile - path: " + path + " type: " + type);
ttvfs::VFSDir *vd = core->vfs.GetDir(path.c_str(), false);
if(!vd)
#if defined(BBGE_BUILD_UNIX)
DIR *dir=0;
dir = opendir(path.c_str());
if (dir)
{
debugLog("Path '" + path + "' does not exist");
return;
dirent *file=0;
while ( (file=readdir(dir)) != NULL )
{
if (file->d_name && strlen(file->d_name) > 4)
{
debugLog(file->d_name);
char *extension=strrchr(file->d_name,'.');
if (extension)
{
debugLog(extension);
if (extension!=NULL)
{
if (strcasecmp(extension,type.c_str())==0)
{
callback(path + std::string(file->d_name), param);
}
}
}
}
}
closedir(dir);
}
else
{
debugLog("FAILED TO OPEN DIR");
}
#endif
#ifdef BBGE_BUILD_WINDOWS
BOOL fFinished;
HANDLE hList;
TCHAR szDir[MAX_PATH+1];
WIN32_FIND_DATA FileData;
int end = path.size()-1;
if (path[end] != '/')
path[end] += '/';
// Get the proper directory path
// \\ %s\\*
if (type.find('.')==std::string::npos)
{
type = "." + type;
}
for(ttvfs::ConstFileIter it = vd->fileIter(); it != vd->fileIterEnd(); ++it)
{
const ttvfs::VFSFile *f = it->second;
const char *e = strrchr(f->name(), '.');
if (e)
{
std::string exs(e);
stringToLower(exs);
if(exs != type)
continue;
}
else if(type.size())
continue;
callback(path + f->name(), param);
//std::string add = "%s*" + type;
//sprintf(szDir, "%s*", path.c_str());
sprintf(szDir, "%s\\*", path.c_str());
stringToUpper(type);
// Get the first file
hList = FindFirstFile(szDir, &FileData);
if (hList == INVALID_HANDLE_VALUE)
{
//printf("No files found\n\n");
debugLog("No files of type " + type + " found in path " + path);
}
else
{
// Traverse through the directory structure
fFinished = FALSE;
while (!fFinished)
{
// Check the object is a directory or not
//printf("%*s%s\n", indent, "", FileData.cFileName);
std::string filename = FileData.cFileName;
//debugLog("found: " + filename);
if (filename.size()>4)
{
std::string filetype = filename.substr(filename.size()-4, filename.size());
stringToUpper(filetype);
//debugLog("comparing: " + filetype + " and: " + type);
if (filetype==type)
{
callback(path+filename, param);
}
}
if (!FindNextFile(hList, &FileData))
{
/*
if (GetLastError() == ERROR_NO_MORE_FILES)
{
fFinished = TRUE;
}
*/
fFinished = TRUE;
}
}
}
FindClose(hList);
#endif
}
std::vector<std::string> getFileList(std::string path, std::string type, int param)
{
std::vector<std::string> list;
#ifdef BBGE_BUILD_WINDOWS
BOOL fFinished;
HANDLE hList;
TCHAR szDir[MAX_PATH+1];
WIN32_FIND_DATA FileData;
// Get the proper directory path
sprintf(szDir, "%s\\*", path.c_str());
// Get the first file
hList = FindFirstFile(szDir, &FileData);
if (hList == INVALID_HANDLE_VALUE)
{
printf("No files found\n\n");
}
else
{
// Traverse through the directory structure
fFinished = FALSE;
while (!fFinished)
{
// Check the object is a directory or not
//printf("%*s%s\n", indent, "", FileData.cFileName);
std::string filename = FileData.cFileName;
if (filename.size()>4 && filename.substr(filename.size()-4, filename.size())==type)
{
//callback(path+filename, param);
list.push_back (filename);
}
if (!FindNextFile(hList, &FileData))
{
/*
if (GetLastError() == ERROR_NO_MORE_FILES)
{
fFinished = TRUE;
}
*/
fFinished = TRUE;
}
}
}
FindClose(hList);
#endif
return list;
}
std::string msg(const std::string &message)

View file

@ -192,11 +192,13 @@ void stringToLower(std::string &s);
void stringToLowerUserData(std::string &s);
void glColor3_256(int r, int g, int b);
float sqr(float x);
bool exists(const std::string &f, bool makeFatal = false, bool skipVFS = false);
bool exists(const std::string &f, bool makeFatal = false);
void errorLog(const std::string &s);
void debugLog(const std::string &s);
char *readFile(std::string path, unsigned long *size_ret = 0);
void forEachFile(std::string path, std::string type, void callback(const std::string &filename, intptr_t param), intptr_t param);
std::string stripEndlineForUnix(const std::string &in);
std::vector<std::string> getFileList(std::string path, std::string type, int param);
#ifdef HAVE_STRCASECMP
static inline int nocasecmp(const std::string &s1, const std::string &s2)
{ return strcasecmp(s1.c_str(), s2.c_str()); }
@ -223,6 +225,19 @@ Vector colorRGB(int r, int g, int b);
#endif
GLuint generateEmptyTexture(int res);
//void pForEachFile(std::string path, std::string type, void callback(const std::string &filename, int param), int param);
/*
void pfread(void *buffer, PHYSFS_uint32 size, PHYSFS_uint32 objs, PHYSFS_file *handle);
void pfseek(PHYSFS_file *handle,PHYSFS_uint64 byte,int origin);
void pfclose(PHYSFS_file *handle);
PHYSFS_file *openRead(const std::string &f);
std::string pLoadStream(const std::string &filename);
void pSaveStream(const std::string &filename, std::ostringstream &os);
*/
void drawCircle(float radius, int steps=1);
bool isVectorInRect(const Vector &vec, const Vector &coord1, const Vector &coord2);

View file

@ -100,7 +100,7 @@ void BitmapText::autoKern()
void BitmapText::loadSpacingMap(const std::string &file)
{
spacingMap.clear();
VFSTextStdStreamIn inFile(file.c_str());
std::ifstream inFile(file.c_str());
std::string line;
while (std::getline(inFile, line))
{

View file

@ -4193,10 +4193,6 @@ void Core::shutdown()
SDL_Quit();
debugLog("OK");
#endif
debugLog("Unloading VFS...");
vfs.Clear();
debugLog("OK");
}
//util funcs
@ -4532,33 +4528,6 @@ void Core::clearGarbage()
i++;
}
// delete leftover buffers from VFS
// FG: TODO: better do that periodically, and not every loop?
for(std::set<ttvfs::VFSFile*>::iterator it = vfsFilesToClear.begin(); it != vfsFilesToClear.end(); ++it)
{
(*it)->dropBuf(true);
(*it)->ref--;
}
vfsFilesToClear.clear();
}
void Core::addVFSFileForDrop(ttvfs::VFSFile *vf)
{
// HACK: because of save/poot.tmp caching and other stuff, we have to clear this always
// TODO: after getting rid of pack/unpackFile, this will be safer and can be done properly
if(strstr(vf->name(), "poot") || strstr(vf->name(), ".tmp"))
{
vf->dropBuf(true);
return;
}
std::set<ttvfs::VFSFile*>::iterator it = vfsFilesToClear.find(vf);
if(it == vfsFilesToClear.end())
{
vf->ref++;
vfsFilesToClear.insert(vf);
}
}
bool Core::canChangeState()
@ -4889,69 +4858,3 @@ int Core::tgaSaveSeries(char *filename,
// ilutGLScreenie();
}
#include "VFSTools.h"
static void _DumpVFS(const std::string a)
{
std::string fn = "vfsdump-" + a + ".txt";
std::ofstream out(fn.c_str());
core->vfs.debugDumpTree(out);
out.close();
}
void Core::setupVFS(const char *extradir /* = NULL */)
{
debugLog("Init VFS...");
if(!ttvfs::checkCompat())
{
errorLog("VFS incompatible!");
exit(1);
}
vfs.LoadFileSysRoot();
vfs.Prepare();
//#ifdef _DEBUG
// _DumpVFS("begin");
//#endif
#ifdef BBGE_BUILD_UNIX
// Load _mods dir from home folder into the data of the existing _mods dir, additionally.
// This does also change the internal path, so that files created using this dir's fullname() will
// automatically be created in the home directory.
ttvfs::VFSDir *moddir = vfs.GetDir("_mods", true);
std::string umods = getUserDataFolder() + "/_mods";
moddir->load(umods.c_str());
std::ostringstream os;
os << "VFS: Mounted _mods as: '" << vfs.GetDir("_mods")->fullname() << "'";
debugLog(os.str());
// Note: the original code to load/save mods is not yet changed.
// This will happen in a later patch.
#endif
if(extradir)
{
std::string msg("VFS extra dir: ");
msg += extradir;
debugLog(msg);
if(vfs.GetDir(extradir))
vfs.Mount(extradir, "");
else
vfs.MountExternalPath(extradir, "");
debugLog("extra dir added.");
}
// Example: everything in _patch dir will be mounted in the game's root dir
// -- place any files/folders there to override those the game uses.
// TODO: remove this later! - When the community datafile update is organized and everything.
vfs.Mount("_patch", "", true);
debugLog("VFS init done!");
//#ifdef _DEBUG
// _DumpVFS("done");
//#endif
}

View file

@ -51,8 +51,6 @@ BUILD_LINUX
#include "FrameBuffer.h"
#include "Shader.h"
#include "VFSIncludes.h"
class ParticleEffect;
class ParticleManager;
@ -1402,14 +1400,6 @@ protected:
int tgaSave(const char *filename, short int width, short int height, unsigned char pixelDepth, unsigned char *imageData);
virtual void onUpdate(float dt);
virtual void onRender(){}
// VFS related
private:
std::set<ttvfs::VFSFile*> vfsFilesToClear; // used for dropBuf() delaying
public:
ttvfs::VFSHelper vfs;
void setupVFS(const char *extradir = NULL);
void addVFSFileForDrop(ttvfs::VFSFile *vf);
};
extern Core *core;

View file

@ -34,8 +34,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "Base.h"
#include "Core.h"
#include "VFSFile.h"
#include "FmodOpenALBridge.h"
#include "al.h"
@ -55,7 +53,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
class OggDecoder {
public:
// Create a decoder that streams from a file.
OggDecoder(ttvfs::VFSFile *fp);
OggDecoder(FILE *fp);
// Create a decoder that streams from a memory buffer.
OggDecoder(const void *data, long data_size);
@ -100,7 +98,7 @@ private:
// Data source. If fp != NULL, the source is that file; otherwise, the
// source is the buffer pointed to by "data" with size "data_size" bytes.
ttvfs::VFSFile *fp;
FILE *fp;
const char *data;
long data_size;
long data_pos; // Current read position for memory buffers
@ -131,38 +129,22 @@ private:
// ov_open_callbacks() call. Note that we rename the fseek() wrapper
// to avoid an identifier collision when building with more recent
// versions of libvorbis.
static int BBGE_ov_header_fseek_wrap(void *f,ogg_int64_t off,int whence){
static int BBGE_ov_header_fseek_wrap(FILE *f,ogg_int64_t off,int whence){
if(f==NULL)return(-1);
ttvfs::VFSFile *vf = (ttvfs::VFSFile*)f;
switch(whence)
{
case SEEK_SET: return vf->seek(off);
case SEEK_CUR: return vf->seekRel(off);
case SEEK_END: return vf->seek(vf->size() - off);
#ifdef __MINGW32__
return fseeko64(f,off,whence);
#elif defined (_WIN32)
return _fseeki64(f,off,whence);
#else
return fseek(f,off,whence);
#endif
}
return -1;
}
static size_t BBGE_ov_fread_wrap(void *ptr, size_t s, size_t count, void *f)
{
if(f==NULL)return(-1);
ttvfs::VFSFile *vf = (ttvfs::VFSFile*)f;
size_t done = vf->read(ptr, s * count);
return done / s;
}
static long BBGE_ov_ftell_wrap(void *f)
{
if(f==NULL)return(-1);
ttvfs::VFSFile *vf = (ttvfs::VFSFile*)f;
return vf->getpos();
}
static int noclose(void *f) {return 0;}
static int noclose(FILE *f) {return 0;}
static const ov_callbacks local_OV_CALLBACKS_NOCLOSE = {
(size_t (*)(void *, size_t, size_t, void *)) BBGE_ov_fread_wrap,
(size_t (*)(void *, size_t, size_t, void *)) fread,
(int (*)(void *, ogg_int64_t, int)) BBGE_ov_header_fseek_wrap,
(int (*)(void *)) noclose, // NULL doesn't work in libvorbis-1.1.2
(long (*)(void *)) BBGE_ov_ftell_wrap
(long (*)(void *)) ftell
};
// Memory I/O callback set.
@ -174,7 +156,7 @@ static const ov_callbacks ogg_memory_callbacks = {
};
OggDecoder::OggDecoder(ttvfs::VFSFile *fp)
OggDecoder::OggDecoder(FILE *fp)
{
for (int i = 0; i < NUM_BUFFERS; i++)
{
@ -535,9 +517,9 @@ static ALenum GVorbisFormat = AL_NONE;
class OpenALSound
{
public:
OpenALSound(ttvfs::VFSFile *_fp, const bool _looping);
OpenALSound(FILE *_fp, const bool _looping);
OpenALSound(void *_data, long _size, const bool _looping);
ttvfs::VFSFile *getFile() const { return fp; }
FILE *getFile() const { return fp; }
const void *getData() const { return data; }
long getSize() const { return size; }
bool isLooping() const { return looping; }
@ -545,21 +527,20 @@ public:
void reference() { refcount++; }
private:
ttvfs::VFSFile * const fp;
FILE * const fp;
void * const data; // Only used if fp==NULL
const long size; // Only used if fp==NULL
const bool looping;
int refcount;
};
OpenALSound::OpenALSound(ttvfs::VFSFile *_fp, const bool _looping)
OpenALSound::OpenALSound(FILE *_fp, const bool _looping)
: fp(_fp)
, data(NULL)
, size(0)
, looping(_looping)
, refcount(1)
{
fp->ref++;
}
OpenALSound::OpenALSound(void *_data, long _size, const bool _looping)
@ -578,11 +559,7 @@ FMOD_RESULT OpenALSound::release()
if (refcount <= 0)
{
if (fp)
{
fp->close();
fp->dropBuf(true); // just in case there is a buffer...
fp->ref--;
}
fclose(fp);
else
free(data);
delete this;
@ -1067,6 +1044,8 @@ FMOD_RESULT OpenALSystem::createSound(const char *name_or_data, const FMOD_MODE
{
assert(!exinfo);
FMOD_RESULT retval = FMOD_ERR_INTERNAL;
// !!! FIXME: if it's not Ogg, we don't have a decoder. I'm lazy. :/
char *fname = (char *) alloca(strlen(name_or_data) + 16);
strcpy(fname, name_or_data);
@ -1074,39 +1053,50 @@ FMOD_RESULT OpenALSystem::createSound(const char *name_or_data, const FMOD_MODE
if (ptr) *ptr = '\0';
strcat(fname, ".ogg");
ttvfs::VFSFile *vf = core->vfs.GetFile(fname);
if(!vf)
// just in case...
#undef fopen
FILE *io = fopen(core->adjustFilenameCase(fname).c_str(), "rb");
if (io == NULL)
return FMOD_ERR_INTERNAL;
if (mode & FMOD_CREATESTREAM)
{
// does it make sense to try to stream from anything else than an actual file on disk?
// Files inside containers are always loaded into memory, unless on-the-fly partial decompression is implemented...
// A typical ogg is < 3 MB in size, if that is preloaded and then decoded over time it should still be a big gain.
if(!vf->isopen())
vf->open(NULL, "rb");
else
vf->seek(0);
*sound = (Sound *) new OpenALSound(vf, (((mode & FMOD_LOOP_OFF) == 0) && (mode & FMOD_LOOP_NORMAL)));
return FMOD_OK;
*sound = (Sound *) new OpenALSound(io, (((mode & FMOD_LOOP_OFF) == 0) && (mode & FMOD_LOOP_NORMAL)));
retval = FMOD_OK;
}
// if we are here, create & preload & pre-decode full buffer
vf->getBuf(); // force early size detection
void *data = malloc(vf->size()); // because release() will use free() ...
if (!(data && vf->getBuf()))
else
{
debugLog("Out of memory for " + std::string(fname));
vf->close();
vf->dropBuf(true);
fseek(io, 0, SEEK_END);
long size = ftell(io);
if (fseek(io, 0, SEEK_SET) != 0)
{
debugLog("Seek error on " + std::string(fname));
fclose(io);
return FMOD_ERR_INTERNAL;
}
memcpy(data, vf->getBuf(), vf->size());
core->addVFSFileForDrop(vf);
*sound = (Sound *) new OpenALSound(data, vf->size(), (((mode & FMOD_LOOP_OFF) == 0) && (mode & FMOD_LOOP_NORMAL)));
return FMOD_OK;
void *data = malloc(size);
if (data == NULL)
{
debugLog("Out of memory for " + std::string(fname));
fclose(io);
return FMOD_ERR_INTERNAL;
}
long nread = fread(data, 1, size, io);
fclose(io);
if (nread != size)
{
debugLog("Failed to read data from " + std::string(fname));
free(data);
return FMOD_ERR_INTERNAL;
}
*sound = (Sound *) new OpenALSound(data, size, (((mode & FMOD_LOOP_OFF) == 0) && (mode & FMOD_LOOP_NORMAL)));
retval = FMOD_OK;
}
return retval;
}
ALBRIDGE(System,createStream,(const char *name_or_data, FMOD_MODE mode, FMOD_CREATESOUNDEXINFO *exinfo, Sound **sound),(name_or_data,mode,exinfo,sound))

View file

@ -123,7 +123,7 @@ void Precacher::precacheTex(const std::string &tex)
void Precacher::precacheList(const std::string &list, void progressCallback())
{
loadProgressCallback = progressCallback;
VFSTextStdStreamIn in(list.c_str());
std::ifstream in(list.c_str());
std::string t;
while (std::getline(in, t))
{

View file

@ -18,8 +18,10 @@ You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "Core.h"
#include "Shader.h"
#ifdef BBGE_BUILD_WINDOWS
#include <sys/stat.h>
#endif
#ifdef BBGE_BUILD_SHADERS
// GL_ARB_shader_objects
@ -86,16 +88,40 @@ void Shader::setValue(float x, float y, float z, float w)
unsigned char *readShaderFile( const char *fileName )
{
debugLog("readShaderFile()");
#ifdef BBGE_BUILD_WINDOWS
FILE *file = fopen( fileName, "r" );
ttvfs::VFSFile *vf = core->vfs.GetFile(fileName);
if(!vf)
return NULL;
if( file == NULL )
{
errorLog("Cannot open shader file!");
return 0;
}
vf->getBuf();
unsigned char *buf = new unsigned char[vf->size() + 1];
memcpy(buf, vf->getBuf(), vf->size() + 1);
core->addVFSFileForDrop(vf);
return buf;
struct _stat fileStats;
if( _stat( fileName, &fileStats ) != 0 )
{
errorLog("Cannot get file stats for shader file!");
return 0;
}
unsigned char *buffer = new unsigned char[fileStats.st_size];
int bytes = fread( buffer, 1, fileStats.st_size, file );
buffer[bytes] = 0;
fclose( file );
debugLog("End readShaderFile()");
return buffer;
#else
debugLog("End readShaderFile()");
return 0;
#endif
}
void Shader::reload()

View file

@ -93,7 +93,7 @@ class SimpleIStringStream {
public:
/* Reuse flag passed to StringStream(char *,int). */
enum Mode {
enum {
/* Make a copy of the buffer (default action). */
COPY,
/* Use the passed-in string pointer as is. Requires the string
@ -212,7 +212,7 @@ class SimpleIStringStream {
/*-------------------------------------------------------------------*/
protected:
private:
char *buffer; // The buffer we're parsing.
char *position; // Our current position in the buffer.
bool freeOnDestroy; // Should we free the buffer when we're destroyed?

View file

@ -21,6 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "SoundManager.h"
#include "Core.h"
#include "Base.h"
#include "PackRead.h"
#if defined(BBGE_BUILD_FMODEX)
#ifdef BBGE_BUILD_FMOD_OPENAL_BRIDGE
@ -133,14 +134,20 @@ FMOD_RESULT F_CALLBACK myopen(const char *name, int unicode, unsigned int *files
{
if (name)
{
ttvfs::VFSFile *vf = core->vfs.GetFile(name);
if(!vf)
return FMOD_ERR_FILE_NOTFOUND;
FILE *fp;
fp = fopen(name, "rb");
if (!fp)
{
return FMOD_ERR_FILE_NOTFOUND;
}
fseek(fp, 0, SEEK_END);
*filesize = ftell(fp);
fseek(fp, 0, SEEK_SET);
vf->open();
*filesize = vf->size();
*handle = (void*)vf;
*userdata = (void *)0x12345678;
*handle = fp;
}
return FMOD_OK;
@ -153,9 +160,7 @@ FMOD_RESULT F_CALLBACK myclose(void *handle, void *userdata)
return FMOD_ERR_INVALID_PARAM;
}
ttvfs::VFSFile *vf = (ttvfs::VFSFile*)handle;
vf->close();
core->addVFSFileForDrop(vf);
fclose((FILE *)handle);
return FMOD_OK;
}
@ -169,8 +174,7 @@ FMOD_RESULT F_CALLBACK myread(void *handle, void *buffer, unsigned int sizebytes
if (bytesread)
{
ttvfs::VFSFile *vf = (ttvfs::VFSFile*)handle;
*bytesread = vf->read((char*)buffer, sizebytes);
*bytesread = (int)fread(buffer, 1, sizebytes, (FILE *)handle);
if (*bytesread < sizebytes)
{
@ -188,8 +192,7 @@ FMOD_RESULT F_CALLBACK myseek(void *handle, unsigned int pos, void *userdata)
return FMOD_ERR_INVALID_PARAM;
}
ttvfs::VFSFile *vf = (ttvfs::VFSFile*)handle;
vf->seek(pos);
fseek((FILE *)handle, pos, SEEK_SET);
return FMOD_OK;
}

View file

@ -18,7 +18,6 @@ You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "Core.h"
#include "TTFFont.h"
@ -47,17 +46,8 @@ void TTFFont::destroy()
void TTFFont::load(const std::string &str, int sz)
{
ttvfs::VFSFile *vf = core->vfs.GetFile(str.c_str());
if(!vf)
{
font = new FTGLTextureFont(str.c_str()); // file not in VFS, just pretend nothing happened
font = new FTGLTextureFont(str.c_str());
font->FaceSize(sz);
return;
}
const unsigned char *buf = (const unsigned char*)vf->getBuf();
create(buf, vf->size(), sz); // this copies the buffer internally
core->addVFSFileForDrop(vf); // so we can delete our own
}
void TTFFont::create(const unsigned char *data, unsigned long datalen, int sz)

View file

@ -468,20 +468,6 @@ void Texture::loadPNG(const std::string &file)
{
if (file.empty()) return;
ttvfs::VFSFile *vf = core->vfs.GetFile(file.c_str());
const char *memptr = vf ? (const char*)vf->getBuf() : NULL;
if(!memptr)
{
debugLog("Can't load PNG file: " + file);
width = 64;
height = 64;
Texture::textureError = TEXERR_FILENOTFOUND;
//exit(1);
return;
}
int memsize = vf->size();
#ifdef BBGE_BUILD_OPENGL
@ -497,11 +483,11 @@ void Texture::loadPNG(const std::string &file)
if (filter == GL_NEAREST)
{
textures[0] = pngBindMem(memptr, memsize, PNG_NOMIPMAPS, pngType, &info, GL_CLAMP_TO_EDGE, filter, filter);
textures[0] = pngBind(file.c_str(), PNG_NOMIPMAPS, pngType, &info, GL_CLAMP_TO_EDGE, filter, filter);
}
else
{
textures[0] = pngBindMem(memptr, memsize, PNG_BUILDMIPMAPS, pngType, &info, GL_CLAMP_TO_EDGE, GL_LINEAR_MIPMAP_LINEAR, filter);
textures[0] = pngBind(file.c_str(), PNG_BUILDMIPMAPS, pngType, &info, GL_CLAMP_TO_EDGE, GL_LINEAR_MIPMAP_LINEAR, filter);
}
@ -529,9 +515,9 @@ void Texture::loadPNG(const std::string &file)
Texture::textureError = TEXERR_FILENOTFOUND;
//exit(1);
}
#endif
core->addVFSFileForDrop(vf);
#endif
}
// internal load functions

View file

@ -1,57 +0,0 @@
#include "Core.h"
#include "VFSFileStream.h"
VFSTextStreamIn::VFSTextStreamIn(const std::string& fn, SimpleIStringStream::Mode strmode /* = TAKE_OVER*/)
: SimpleIStringStream()
{
_init(fn.c_str(), strmode);
}
VFSTextStreamIn::VFSTextStreamIn(const char *fn, SimpleIStringStream::Mode strmode /* = TAKE_OVER*/)
: SimpleIStringStream()
{
_init(fn, strmode);
}
void VFSTextStreamIn::_init(const char *fn, SimpleIStringStream::Mode strmode)
{
ttvfs::VFSFile *vf = core->vfs.GetFile(fn);
if(vf)
{
vf->open(NULL, "r");
setString((char*)vf->getBuf(), strmode);
vf->close();
if(strmode == TAKE_OVER)
vf->dropBuf(false);
}
else
error = true;
}
VFSTextStdStreamIn::VFSTextStdStreamIn(const std::string& fn, SimpleIStringStream::Mode strmode /* = TAKE_OVER*/)
: std::istringstream()
{
_init(fn.c_str(), strmode);
}
VFSTextStdStreamIn::VFSTextStdStreamIn(const char *fn, SimpleIStringStream::Mode strmode /* = TAKE_OVER*/)
: std::istringstream()
{
_init(fn, strmode);
}
void VFSTextStdStreamIn::_init(const char *fn, SimpleIStringStream::Mode strmode)
{
ttvfs::VFSFile *vf = core->vfs.GetFile(fn);
if(vf)
{
vf->open(NULL, "r");
str((char*)vf->getBuf()); // stringstream will always make a copy
vf->close();
if(strmode == SimpleIStringStream::TAKE_OVER)
core->addVFSFileForDrop(vf);
}
else
this->setstate(std::ios_base::failbit);
}

View file

@ -1,43 +0,0 @@
#ifndef VFS_FILE_STREAM_H
#define VFS_FILE_STREAM_H
#include "SimpleIStringStream.h"
class VFSTextStreamIn : public SimpleIStringStream
{
/* This class is an adapter to support STL-like read-only file streams for VFS files,
* using the SimpleIStringStream for performance reasons.
*
* strmode: one of COPY, REUSE, TAKE_OVER, see SimpleIStringStream.h
*/
public:
VFSTextStreamIn(const char *fn, SimpleIStringStream::Mode strmode = TAKE_OVER);
VFSTextStreamIn(const std::string& fn, SimpleIStringStream::Mode strmode = TAKE_OVER);
void close() {}
private:
void _init(const char *fn, SimpleIStringStream::Mode strmode);
};
class VFSTextStdStreamIn : public std::istringstream
{
/* This class is an adapter to support STL-like read-only file streams for VFS files,
* using std::istringstream.
*
* strmode: one of COPY, REUSE, TAKE_OVER, see SimpleIStringStream.h
* - Note: The file's content will always be copied, regardless of strmode setting.
* However, TAKE_OVER will drop the internal buffer.
*/
public:
VFSTextStdStreamIn(const char *fn, SimpleIStringStream::Mode strmode = SimpleIStringStream::TAKE_OVER);
VFSTextStdStreamIn(const std::string& fn, SimpleIStringStream::Mode strmode = SimpleIStringStream::TAKE_OVER);
void close() {}
private:
void _init(const char *fn, SimpleIStringStream::Mode strmode);
};
#endif

View file

@ -1,9 +0,0 @@
#ifndef CUSTOM_VFS_INCLUDES_H
#define CUSTOM_VFS_INCLUDES_H
#include "VFS.h"
#include "VFSFileStream.h"
#include "VFSFile.h"
#endif

View file

@ -20,13 +20,33 @@ using namespace std;
#include <OpenGL/gl.h>
*/
#include "Base.h"
#include "Core.h"
#include "lvpa/ByteBuffer.h"
#include "SDL_endian.h"
//glFont header
#include "glfont2.h"
using namespace glfont;
static int read_int(ifstream &input)
{
int buffer;
input.read((char *)&buffer, 4);
return SDL_SwapLE32(buffer);
}
static float read_float(ifstream &input)
{
union
{
int i;
float f;
} buffer;
input.read((char *)&buffer.i, 4);
buffer.i = SDL_SwapLE32(buffer.i);
return buffer.f;
}
//*******************************************************************
//GLFont Class Implementation
@ -50,6 +70,7 @@ GLFont::~GLFont ()
//*******************************************************************
bool GLFont::Create (const char *file_name, int tex, bool loadTexture)
{
ifstream input;
int num_chars, num_tex_bytes;
char *tex_bytes;
@ -57,23 +78,18 @@ bool GLFont::Create (const char *file_name, int tex, bool loadTexture)
Destroy();
//Open input file
ttvfs::VFSFile *vf = core->vfs.GetFile(file_name);
if(!vf)
input.open(file_name, ios::in | ios::binary);
if (!input)
return false;
lvpa::ByteBuffer bb;
bb.append(vf->getBuf(), vf->size());
core->addVFSFileForDrop(vf);
lvpa::uint32 dummy;
// Read the header from file
header.tex = tex;
bb >> dummy; // skip tex field
bb >> header.tex_width;
bb >> header.tex_height;
bb >> header.start_char;
bb >> header.end_char;
bb >> dummy; // skip chars field
input.seekg(4, ios::cur); // skip tex field
header.tex_width = read_int(input);
header.tex_height = read_int(input);
header.start_char = read_int(input);
header.end_char = read_int(input);
input.seekg(4, ios::cur); // skip chars field
std::ostringstream os;
os << "tex_width: " << header.tex_width << " tex_height: " << header.tex_height;
@ -87,19 +103,18 @@ bool GLFont::Create (const char *file_name, int tex, bool loadTexture)
//Read character array
for (int i = 0; i < num_chars; i++)
{
bb >> header.chars[i].dx;
bb >> header.chars[i].dy;
bb >> header.chars[i].tx1;
bb >> header.chars[i].ty1;
bb >> header.chars[i].tx2;
bb >> header.chars[i].ty2;
header.chars[i].dx = read_float(input);
header.chars[i].dy = read_float(input);
header.chars[i].tx1 = read_float(input);
header.chars[i].ty1 = read_float(input);
header.chars[i].tx2 = read_float(input);
header.chars[i].ty2 = read_float(input);
}
//Read texture pixel data
num_tex_bytes = header.tex_width * header.tex_height * 2;
tex_bytes = new char[num_tex_bytes];
//input.read(tex_bytes, num_tex_bytes);
bb.read(tex_bytes, num_tex_bytes);
input.read(tex_bytes, num_tex_bytes);
//Build2DMipmaps(3, header.tex_width, header.tex_height, GL_UNSIGNED_BYTE, tex_bytes, 1);
@ -135,6 +150,9 @@ bool GLFont::Create (const char *file_name, int tex, bool loadTexture)
//Free texture pixels memory
delete[] tex_bytes;
//Close input file
input.close();
//Return successfully
return true;
}

View file

@ -22,8 +22,6 @@ must not be misrepresented as being the original software.
distribution.
*/
// hacked VFS support into this version.
#include <ctype.h>
#ifdef TIXML_USE_STL
@ -33,8 +31,6 @@ distribution.
#include "tinyxml.h"
#include "Core.h"
FILE* TiXmlFOpen( const char* filename, const char* mode );
bool TiXmlBase::condenseWhiteSpace = true;
@ -927,11 +923,12 @@ bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding )
value = filename;
// reading in binary mode so that tinyxml can normalize the EOL
ttvfs::VFSFile* file = core->vfs.GetFile(value.c_str());
FILE* file = TiXmlFOpen( value.c_str (), "rb" );
if ( file )
{
bool result = LoadFile( file, encoding );
fclose( file );
return result;
}
else
@ -941,7 +938,7 @@ bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding )
}
}
bool TiXmlDocument::LoadFile( ttvfs::VFSFile* file, TiXmlEncoding encoding )
bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding )
{
if ( !file )
{
@ -954,15 +951,10 @@ bool TiXmlDocument::LoadFile( ttvfs::VFSFile* file, TiXmlEncoding encoding )
location.Clear();
// Get the file size, so we can pre-allocate the string. HUGE speed impact.
char* buf = (char*)file->getBuf();
if ( !buf )
{
SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
return false;
}
long length = file->size();
long length = 0;
fseek( file, 0, SEEK_END );
length = ftell( file );
fseek( file, 0, SEEK_SET );
// Strange case, but good to handle up front.
if ( length <= 0 )
@ -992,6 +984,15 @@ bool TiXmlDocument::LoadFile( ttvfs::VFSFile* file, TiXmlEncoding encoding )
}
*/
char* buf = new char[ length+1 ];
buf[0] = 0;
if ( fread( buf, length, 1, file ) != 1 ) {
delete [] buf;
SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
return false;
}
// Process the buffer in place to normalize new lines. (See comment above.)
// Copies from the 'p' to 'q' pointer, where p can advance faster if
// a newline-carriage return is hit.
@ -1030,16 +1031,13 @@ bool TiXmlDocument::LoadFile( ttvfs::VFSFile* file, TiXmlEncoding encoding )
Parse( buf, 0, encoding );
core->addVFSFileForDrop(file);
delete [] buf;
return !Error();
}
bool TiXmlDocument::SaveFile( const char * filename ) const
{
// FG: TODO: use VFS stuff here as well
// The old c stuff lives on...
FILE* fp = TiXmlFOpen( filename, "w" );
if ( fp )

View file

@ -53,11 +53,6 @@ distribution.
#define TIXML_STRING TiXmlString
#endif
namespace ttvfs
{
class VFSFile;
}
// Deprecated library function hell. Compilers want to use the
// new safe versions. This probably doesn't fully address the problem,
// but it gets closer. There are too many compilers for me to fully
@ -1422,7 +1417,7 @@ public:
will be interpreted as an XML file. TinyXML doesn't stream in XML from the current
file location. Streaming may be added in the future.
*/
bool LoadFile( ttvfs::VFSFile*, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
bool LoadFile( FILE*, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
/// Save a file using the given FILE*. Returns true if successful.
bool SaveFile( FILE* ) const;

View file

@ -170,8 +170,6 @@ INCLUDE_DIRECTORIES(${LUA_INCLUDE_DIR})
INCLUDE_DIRECTORIES(${OGGVORBIS_INCLUDE_DIRS})
INCLUDE_DIRECTORIES(${SDL_INCLUDE_DIR})
INCLUDE_DIRECTORIES(${OPENAL_INCLUDE_DIR})
INCLUDE_DIRECTORIES(${EXTLIBDIR}/ttvfs)
INCLUDE_DIRECTORIES(${EXTLIBDIR}/lvpa)
# Custom build ID: e.g. "-custom", " (my very own build)"
@ -380,7 +378,6 @@ SET(BBGE_SRCS
${BBGEDIR}/tinyxmlerror.cpp
${BBGEDIR}/tinyxmlparser.cpp
${BBGEDIR}/glfont2.cpp
${BBGEDIR}/VFSFileStream.cpp
${COCOA_SRCS}
${EXTLIBDIR}/glpng/glpng.c
${EXTLIBDIR}/glpng/png/png.c
@ -560,9 +557,6 @@ SET(LUA_SRCS
${LUASRCDIR}/lmathlib.c
)
ADD_SUBDIRECTORY(ExternalLibs/ttvfs)
SET(OPTIONAL_LIBS ${OPTIONAL_LIBS} ttvfs)
IF(MACOSX)
SET(OPTIONAL_LIBS ${OPTIONAL_LIBS} "-framework Carbon")

View file

@ -97,11 +97,9 @@ extern int APIENTRY pngLoadRawF(FILE *file, pngRawInfo *rawinfo);
extern int APIENTRY pngLoad(const char *filename, int mipmap, int trans, pngInfo *info);
extern int APIENTRY pngLoadF(FILE *file, int mipmap, int trans, pngInfo *info);
extern int APIENTRY pngLoadMem(const char *mem, int size, int mipmap, int trans, pngInfo *info);
extern unsigned int APIENTRY pngBind(const char *filename, int mipmap, int trans, pngInfo *info, int wrapst, int minfilter, int magfilter);
extern unsigned int APIENTRY pngBindF(FILE *file, int mipmap, int trans, pngInfo *info, int wrapst, int minfilter, int magfilter);
extern unsigned int APIENTRY pngBindMem(const char *mem, int size, int mipmap, int trans, pngInfo *info, int wrapst, int minfilter, int magfilter);
extern void APIENTRY pngSetStencil(unsigned char red, unsigned char green, unsigned char blue);
extern void APIENTRY pngSetAlphaCallback(unsigned char (*callback)(unsigned char red, unsigned char green, unsigned char blue));

View file

@ -691,14 +691,6 @@ unsigned int APIENTRY pngBindF(FILE *file, int mipmap, int trans, pngInfo *info,
return 0;
}
unsigned int APIENTRY pngBindMem(const char *mem, int size, int mipmap, int trans, pngInfo *info, int wrapst, int minfilter, int magfilter) {
unsigned int id = SetParams(wrapst, magfilter, minfilter);
if (id != 0 && pngLoadMem(mem, size, mipmap, trans, info))
return id;
return 0;
}
void APIENTRY pngSetStencil(unsigned char red, unsigned char green, unsigned char blue) {
StencilRed = red, StencilGreen = green, StencilBlue = blue;
}
@ -725,332 +717,3 @@ void APIENTRY pngSetStandardOrientation(int standardorientation) {
StandardOrientation = standardorientation;
}
// -- added memory read functions --
/*pointer to a new input function that takes as its
arguments a pointer to a png_struct, a pointer to
a location where input data can be stored, and a 32-bit
unsigned int that is the number of bytes to be read.
To exit and output any fatal error messages the new write
function should call png_error(png_ptr, "Error msg"). */
typedef struct glpng_memread_struct
{
png_bytep mem;
png_size_t rpos;
} glpng_memread;
void glpng_read_mem(png_structp png, png_bytep dst, png_size_t size)
{
glpng_memread *mr = (glpng_memread*)png->io_ptr;
memcpy(dst, mr->mem + mr->rpos, size);
mr->rpos += size;
}
int APIENTRY pngLoadMem(const char *mem, int size, int mipmap, int trans, pngInfo *pinfo) {
GLint pack, unpack;
unsigned char header[8];
png_structp png;
png_infop info;
png_infop endinfo;
png_bytep data, data2;
png_bytep *row_p;
double fileGamma;
png_uint_32 width, height, rw, rh;
int depth, color;
png_uint_32 i;
glpng_memread memread;
if(size < 8)
return 0; // error
memcpy(header, mem, 8);
if (!png_check_sig(header, 8))
return 0;
png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
info = png_create_info_struct(png);
endinfo = png_create_info_struct(png);
// DH: added following lines
if (setjmp(png->jmpbuf))
{
png_destroy_read_struct(&png, &info, &endinfo);
return 0;
}
// ~DH
memread.rpos = 0;
memread.mem = ((png_bytep)mem) + 8;
png_set_read_fn(png, (voidp)&memread, glpng_read_mem);
png_set_sig_bytes(png, 8);
png_read_info(png, info);
png_get_IHDR(png, info, &width, &height, &depth, &color, NULL, NULL, NULL);
if (pinfo != NULL) {
pinfo->Width = width;
pinfo->Height = height;
pinfo->Depth = depth;
}
if (MaxTextureSize == 0)
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &MaxTextureSize);
#ifdef SUPPORTS_PALETTE_EXT
#ifdef _WIN32
if (PalettedTextures == -1)
PalettedTextures = ExtSupported("GL_EXT_paletted_texture") && (strstr((const char *) glGetString(GL_VERSION), "1.1.0 3Dfx Beta") == NULL);
if (PalettedTextures) {
if (glColorTableEXT == NULL) {
glColorTableEXT = (PFNGLCOLORTABLEEXTPROC) wglGetProcAddress("glColorTableEXT");
if (glColorTableEXT == NULL)
PalettedTextures = 0;
}
}
#endif
#endif
if (PalettedTextures == -1)
PalettedTextures = 0;
if (color == PNG_COLOR_TYPE_GRAY || color == PNG_COLOR_TYPE_GRAY_ALPHA)
png_set_gray_to_rgb(png);
if (color&PNG_COLOR_MASK_ALPHA && trans != PNG_ALPHA) {
png_set_strip_alpha(png);
color &= ~PNG_COLOR_MASK_ALPHA;
}
if (!(PalettedTextures && mipmap >= 0 && trans == PNG_SOLID))
if (color == PNG_COLOR_TYPE_PALETTE)
png_set_expand(png);
/*--GAMMA--*/
checkForGammaEnv();
if (png_get_gAMA(png, info, &fileGamma))
png_set_gamma(png, screenGamma, fileGamma);
else
png_set_gamma(png, screenGamma, 1.0/2.2);
png_read_update_info(png, info);
data = (png_bytep) malloc(png_get_rowbytes(png, info)*height);
row_p = (png_bytep *) malloc(sizeof(png_bytep)*height);
for (i = 0; i < height; i++) {
if (StandardOrientation)
row_p[height - 1 - i] = &data[png_get_rowbytes(png, info)*i];
else
row_p[i] = &data[png_get_rowbytes(png, info)*i];
}
png_read_image(png, row_p);
free(row_p);
rw = SafeSize(width), rh = SafeSize(height);
if (rw != width || rh != height) {
const int channels = png_get_rowbytes(png, info)/width;
data2 = (png_bytep) malloc(rw*rh*channels);
/* Doesn't work on certain sizes */
/* if (gluScaleImage(glformat, width, height, GL_UNSIGNED_BYTE, data, rw, rh, GL_UNSIGNED_BYTE, data2) != 0)
return 0;
*/
Resize(channels, data, width, height, data2, rw, rh);
width = rw, height = rh;
free(data);
data = data2;
}
{ /* OpenGL stuff */
glGetIntegerv(GL_PACK_ALIGNMENT, &pack);
glGetIntegerv(GL_UNPACK_ALIGNMENT, &unpack);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
#ifdef SUPPORTS_PALETTE_EXT
if (PalettedTextures && mipmap >= 0 && trans == PNG_SOLID && color == PNG_COLOR_TYPE_PALETTE) {
png_colorp pal;
int cols;
GLint intf;
if (pinfo != NULL) pinfo->Alpha = 0;
png_get_PLTE(png, info, &pal, &cols);
switch (cols) {
case 1<<1: intf = GL_COLOR_INDEX1_EXT; break;
case 1<<2: intf = GL_COLOR_INDEX2_EXT; break;
case 1<<4: intf = GL_COLOR_INDEX4_EXT; break;
case 1<<8: intf = GL_COLOR_INDEX8_EXT; break;
case 1<<12: intf = GL_COLOR_INDEX12_EXT; break;
case 1<<16: intf = GL_COLOR_INDEX16_EXT; break;
default:
/*printf("Warning: Colour depth %i not recognised\n", cols);*/
return 0;
}
glColorTableEXT(GL_TEXTURE_2D, GL_RGB8, cols, GL_RGB, GL_UNSIGNED_BYTE, pal);
glTexImage2D(GL_TEXTURE_2D, mipmap, intf, width, height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, data);
}
else
#endif
if (trans == PNG_SOLID || trans == PNG_ALPHA || trans == PNG_LUMINANCEALPHA || color == PNG_COLOR_TYPE_RGB_ALPHA || color == PNG_COLOR_TYPE_GRAY_ALPHA) {
GLenum glformat;
GLint glcomponent;
switch (color) {
case PNG_COLOR_TYPE_GRAY:
case PNG_COLOR_TYPE_RGB:
case PNG_COLOR_TYPE_PALETTE:
glformat = GL_RGB;
glcomponent = 3;
if (pinfo != NULL) pinfo->Alpha = 0;
break;
case PNG_COLOR_TYPE_GRAY_ALPHA:
case PNG_COLOR_TYPE_RGB_ALPHA:
glformat = GL_RGBA;
glcomponent = 4;
if (pinfo != NULL) pinfo->Alpha = 8;
break;
default:
/*puts("glformat not set");*/
return 0;
}
if (trans == PNG_LUMINANCEALPHA)
glformat = GL_LUMINANCE_ALPHA;
if (mipmap == PNG_BUILDMIPMAPS)
Build2DMipmaps(glcomponent, width, height, glformat, data, 1);
else if (mipmap == PNG_SIMPLEMIPMAPS)
Build2DMipmaps(glcomponent, width, height, glformat, data, 0);
else
glTexImage2D(GL_TEXTURE_2D, mipmap, glcomponent, width, height, 0, glformat, GL_UNSIGNED_BYTE, data);
}
else {
png_bytep p, endp, q;
int r, g, b, a;
p = data, endp = p+width*height*3;
q = data2 = (png_bytep) malloc(sizeof(png_byte)*width*height*4);
if (pinfo != NULL) pinfo->Alpha = 8;
#define FORSTART \
do { \
r = *p++; /*red */ \
g = *p++; /*green*/ \
b = *p++; /*blue */ \
*q++ = r; \
*q++ = g; \
*q++ = b;
#define FOREND \
q++; \
} while (p != endp);
#define ALPHA *q
switch (trans) {
case PNG_CALLBACK:
FORSTART
ALPHA = AlphaCallback((unsigned char) r, (unsigned char) g, (unsigned char) b);
FOREND
break;
case PNG_STENCIL:
FORSTART
if (r == StencilRed && g == StencilGreen && b == StencilBlue)
ALPHA = 0;
else
ALPHA = 255;
FOREND
break;
case PNG_BLEND1:
FORSTART
a = r+g+b;
if (a > 255) ALPHA = 255; else ALPHA = a;
FOREND
break;
case PNG_BLEND2:
FORSTART
a = r+g+b;
if (a > 255*2) ALPHA = 255; else ALPHA = a/2;
FOREND
break;
case PNG_BLEND3:
FORSTART
ALPHA = (r+g+b)/3;
FOREND
break;
case PNG_BLEND4:
FORSTART
a = r*r+g*g+b*b;
if (a > 255) ALPHA = 255; else ALPHA = a;
FOREND
break;
case PNG_BLEND5:
FORSTART
a = r*r+g*g+b*b;
if (a > 255*2) ALPHA = 255; else ALPHA = a/2;
FOREND
break;
case PNG_BLEND6:
FORSTART
a = r*r+g*g+b*b;
if (a > 255*3) ALPHA = 255; else ALPHA = a/3;
FOREND
break;
//HACK: disabling this for now
/*
case PNG_BLEND7:
FORSTART
a = r*r+g*g+b*b;
if (a > 255*255) ALPHA = 255; else ALPHA = (int) (sqrt(float(a)));
FOREND
*/
break;
}
#undef FORSTART
#undef FOREND
#undef ALPHA
if (mipmap == PNG_BUILDMIPMAPS)
Build2DMipmaps(4, width, height, GL_RGBA, data2, 1);
else if (mipmap == PNG_SIMPLEMIPMAPS)
Build2DMipmaps(4, width, height, GL_RGBA, data2, 0);
else
glTexImage2D(GL_TEXTURE_2D, mipmap, 4, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data2);
free(data2);
}
glPixelStorei(GL_PACK_ALIGNMENT, pack);
glPixelStorei(GL_UNPACK_ALIGNMENT, unpack);
} /* OpenGL end */
png_read_end(png, endinfo);
png_destroy_read_struct(&png, &info, &endinfo);
free(data);
return 1;
}

View file

@ -1,340 +0,0 @@
#ifndef BYTEBUFFER_H
#define BYTEBUFFER_H
#include "LVPACommon.h"
#include "ByteConverter.h"
#include <string.h> // for memcpy
LVPA_NAMESPACE_START
#define BB_MAKE_WRITE_OP(T) inline ByteBuffer& operator<<(T val) { append<T>(val); return *this; }
#define BB_MAKE_READ_OP(T) inline ByteBuffer& operator>>(T &val) { val = read<T>(); return *this; }
class ByteBuffer
{
public:
typedef void (*delete_func)(void*);
enum Mode // for creation with existing pointers
{
COPY, //- Make a copy of the buffer (default action).
REUSE, //- Use the passed-in buffer as is. Requires the pointer
// to remain valid over the life of this object.
TAKE_OVER, //- Take over the passed-in buffer; it will be deleted on object destruction.
};
class Exception
{
public:
Exception(const ByteBuffer *bb, const char *act, uint32 sp = 0)
{
action = act;
rpos = bb->rpos();
wpos = bb->wpos();
sizeparam = sp;
cursize = bb->size();
}
uint32 rpos, wpos, sizeparam, cursize;
const char *action;
};
private:
delete_func _delfunc;
uint32 _rpos, // read position, [0 ... _size]
_wpos, // write position, [0 ... _size]
_res, // reserved buffer size, [0 ... _size ... _res]
_size; // used buffer size
uint8 *_buf; // the ptr to the buffer that holds all the bytes
bool _mybuf; // if true, destructor deletes buffer
bool _growable; // default true, if false, buffer will not re-allocate more space
public:
ByteBuffer()
: _rpos(0), _wpos(0), _buf(NULL), _size(0), _growable(true)
{
_allocate(128);
}
ByteBuffer(uint32 res)
: _rpos(0), _wpos(0), _buf(NULL), _size(0), _growable(true)
{
_allocate(res);
}
ByteBuffer(const ByteBuffer &buf, uint32 extra = 0)
: _rpos(0), _wpos(0), _buf(NULL), _size(0), _growable(true)
{
_allocate(buf.size() + extra + 64);
append(buf);
}
ByteBuffer(void *buf, uint32 size, Mode mode = COPY, delete_func del = NULL, uint32 extra = 0)
: _rpos(0), _wpos(0), _size(size), _buf(NULL), _growable(true), _delfunc(del),
_mybuf(false) // for mode == REUSE
{
switch(mode)
{
case COPY:
_allocate(size + extra);
append(buf, size);
break;
case TAKE_OVER:
_mybuf = true; // fallthrough
case REUSE:
_buf = (uint8*)buf;
_res = size;
}
}
virtual ~ByteBuffer()
{
clear();
}
void clear(void)
{
_delete();
reset();
}
inline void reset(void)
{
_rpos = _wpos = _size = 0;
}
void resize(uint32 newsize)
{
reserve(newsize);
_rpos = 0;
_wpos = newsize;
_size = newsize;
}
void reserve(uint32 newsize)
{
if(_res < newsize)
_allocate(newsize);
}
// ---------------------- Write methods -----------------------
BB_MAKE_WRITE_OP(uint8);
BB_MAKE_WRITE_OP(uint16);
BB_MAKE_WRITE_OP(uint32);
BB_MAKE_WRITE_OP(uint64);
BB_MAKE_WRITE_OP(float);
BB_MAKE_WRITE_OP(double);
BB_MAKE_WRITE_OP(int);
ByteBuffer &operator<<(bool value)
{
append<char>((char)value);
return *this;
}
ByteBuffer &operator<<(const char *str)
{
append((uint8 *)str, str ? strlen(str) : 0);
append((uint8)0);
return *this;
}
ByteBuffer &operator<<(const std::string &value)
{
append((uint8 *)value.c_str(), value.length());
append((uint8)0);
return *this;
}
// -------------------- Read methods --------------------
BB_MAKE_READ_OP(uint8);
BB_MAKE_READ_OP(uint16);
BB_MAKE_READ_OP(uint32);
BB_MAKE_READ_OP(uint64);
BB_MAKE_READ_OP(float);
BB_MAKE_READ_OP(double);
BB_MAKE_READ_OP(int);
ByteBuffer &operator>>(bool &value)
{
value = read<char>() > 0 ? true : false;
return *this;
}
uint8 operator[](uint32 pos)
{
return read<uint8>(pos);
}
ByteBuffer &operator>>(std::string& value)
{
value.clear();
char c;
while(readable() && (c = read<char>()))
value += c;
return *this;
}
// --------------------------------------------------
uint32 rpos() const { return _rpos; }
uint32 rpos(uint32 rpos)
{
_rpos = rpos < size() ? rpos : size();
return _rpos;
}
uint32 wpos() const { return _wpos; }
uint32 wpos(uint32 wpos)
{
_wpos = wpos < size() ? wpos : size();
return _wpos;
}
template <typename T> T read()
{
T r = read<T>(_rpos);
_rpos += sizeof(T);
return r;
}
template <typename T> T read(uint32 pos) const
{
if(pos + sizeof(T) > size())
throw Exception(this, "read", sizeof(T));
T val = *((T const*)(_buf + pos));
ToLittleEndian<T>(val);
return val;
}
void read(void *dest, uint32 len)
{
if (_rpos + len <= size())
memcpy(dest, &_buf[_rpos], len);
else
throw Exception(this, "read-into", len);
_rpos += len;
}
inline const uint8 *contents() const { return _buf; }
inline uint8 *contents() { return _buf; }
inline uint32 size() const { return _size; }
inline uint32 bytes() const { return size(); }
inline uint32 bits() const { return bytes() * 8; }
inline uint32 capacity() const { return _res; }
inline uint32 readable(void) const { return size() - rpos(); }
inline uint32 writable(void) const { return size() - wpos(); } // free space left before realloc will occur
template <typename T> void append(T value)
{
ToLittleEndian<T>(value);
_enlargeIfReq(_wpos + sizeof(T));
*((T*)(_buf + _wpos)) = value;
_wpos += sizeof(T);
if(_size < _wpos)
_size = _wpos;
}
void append(const void *src, uint32 bytes)
{
if (!bytes) return;
_enlargeIfReq(_wpos + bytes);
memcpy(_buf + _wpos, src, bytes);
_wpos += bytes;
if(_size < _wpos)
_size = _wpos;
}
void append(const ByteBuffer& buffer)
{
if(buffer.size())
append(buffer.contents(), buffer.size());
}
void put(uint32 pos, const void *src, uint32 bytes)
{
memcpy(_buf + pos, src, bytes);
}
template <typename T> void put(uint32 pos, T value)
{
if(pos >= size())
{
throw Exception(this, "put", sizeof(T));
}
ToLittleEndian<T>(value);
*((T*)(_buf + pos)) = value;
}
inline bool growable(void) { return _growable; }
inline void growable(bool b) { _growable = b; }
// dangerous functions
void _setPtr(void *p)
{
_buf = (uint8*)p;
}
protected:
void _delete(void)
{
if(_mybuf)
{
if(_delfunc)
_delfunc(_buf);
else
delete [] _buf;
_buf = NULL;
_res = 0;
}
}
// allocate larger buffer and copy contents. if we own the current buffer, delete old, otherwise, leave it as it is.
void _allocate(uint32 s)
{
if(!_growable && _buf) // only throw if we already have a buf
throw Exception(this, "_alloc+locked", s);
uint8 *newbuf = (uint8*)malloc(s);
if(_buf)
{
memcpy(newbuf, _buf, _size);
_delete();
}
_delfunc = free;
_buf = newbuf;
_res = s;
_mybuf = true;
}
void _enlargeIfReq(uint32 minSize)
{
if(_res < minSize)
{
uint32 a = _res * 2;
if(a < minSize) // fallback if doubling the space was not enough
a += minSize;
_allocate(a);
}
}
};
#undef BB_MAKE_WRITE_OP
#undef BB_MAKE_READ_OP
LVPA_NAMESPACE_END
#endif

View file

@ -1,46 +0,0 @@
#ifndef BYTECONVERTER_H
#define BYTECONVERTER_H
#include <algorithm>
#include "LVPAInternal.h" // this is important to fix up any possible ***_ENDIAN misconfigurations
LVPA_NAMESPACE_START
namespace ByteConverter
{
template<size_t T>
inline void convert(char *val)
{
std::swap(*val, *(val + T - 1));
convert<T - 2>(val + 1);
}
template<> inline void convert<0>(char *) {}
template<> inline void convert<1>(char *) {}
template<typename T>
inline void apply(T *val)
{
convert<sizeof(T)>((char *)(val));
}
}
#if IS_BIG_ENDIAN
template<typename T> inline void ToLittleEndian(T& val) { ByteConverter::apply<T>(&val); }
template<typename T> inline void ToBigEndian(T&) { }
#else
template<typename T> inline void ToLittleEndian(T&) { }
template<typename T> inline void ToBigEndian(T& val) { ByteConverter::apply<T>(&val); }
#endif
template<typename T> void ToLittleEndian(T*); // will generate link error
template<typename T> void ToBigEndian(T*); // will generate link error
inline void ToLittleEndian(uint8&) { }
inline void ToLittleEndian(int8&) { }
inline void ToBigEndian(uint8&) { }
inline void ToBigEndian( int8&) { }
LVPA_NAMESPACE_END
#endif

View file

@ -1,44 +0,0 @@
#ifndef LVPA_COMMON_H
#define LVPA_COMMON_H
#include "LVPACompileConfig.h"
#include <stdlib.h>
#include <cstring>
LVPA_NAMESPACE_START
#ifdef _MSC_VER
typedef __int64 int64;
typedef long int32;
typedef short int16;
typedef char int8;
typedef unsigned __int64 uint64;
typedef unsigned long uint32;
typedef unsigned short uint16;
typedef unsigned char uint8;
#else
typedef long long int64;
typedef int int32;
typedef short int16;
typedef char int8;
typedef unsigned long long uint64;
typedef unsigned int uint32;
typedef unsigned short uint16;
typedef unsigned char uint8;
#endif
struct memblock
{
memblock() : ptr(NULL), size(0) {}
memblock(uint8 *p, uint32 s) : size(s), ptr(p) {}
uint8 *ptr;
uint32 size;
};
LVPA_NAMESPACE_END
#endif

View file

@ -1,28 +0,0 @@
#ifndef LVPA_COMPILE_CONFIG
#define LVPA_COMPILE_CONFIG
// TODO ADD TEXT
#define LVPA_NAMESPACE lvpa
//#define LVPA_SUPPORT_ZLIB
#define LVPA_SUPPORT_LZMA
//#define LVPA_SUPPORT_LZO
#define LVPA_SUPPORT_LZF
// ------ End of config ------
#ifdef LVPA_NAMESPACE
# define LVPA_NAMESPACE_START namespace LVPA_NAMESPACE {
# define LVPA_NAMESPACE_END }
# define LVPA_NAMESPACE_IMPL LVPA_NAMESPACE::
namespace LVPA_NAMESPACE {} // predeclare namespace to make compilers happy
#else
# define LVPA_NAMESPACE_START
# define LVPA_NAMESPACE_END
# define LVPA_NAMESPACE_IMPL
#endif
#endif

View file

@ -1,201 +0,0 @@
#ifndef LVPA_INTERNAL_H
#define LVPA_INTERNAL_H
#ifdef _DEBUG
# define DBG if(1)
# define DEBUG(x) x;
# define logdebug(...) { printf(__VA_ARGS__); putchar('\n'); }
# define logerror(...) { fputs("ERROR: ",stdout); printf(__VA_ARGS__); putchar('\n'); }
#else
# define DBG if(0)
# define DEBUG(x)
# define logdebug(...)
# define logerror(...)
#endif
//////////////////////////////////////
// Platform defines
//////////////////////////////////////
#define PLATFORM_WIN32 0
#define PLATFORM_UNIX 1
#define PLATFORM_APPLE 2
#define PLATFORM_INTEL 3
#if defined( __WIN32__ ) || defined( WIN32 ) || defined( _WIN32 )
# define PLATFORM PLATFORM_WIN32
#elif defined( __APPLE_CC__ )
# define PLATFORM PLATFORM_APPLE
#elif defined( __INTEL_COMPILER )
# define PLATFORM PLATFORM_INTEL
#else
# define PLATFORM PLATFORM_UNIX
#endif
#define COMPILER_MICROSOFT 0
#define COMPILER_GNU 1
#define COMPILER_BORLAND 2
#define COMPILER_INTEL 3
#ifdef _MSC_VER
# define COMPILER COMPILER_MICROSOFT
#elif defined( __BORLANDC__ )
# define COMPILER COMPILER_BORLAND
#elif defined( __INTEL_COMPILER )
# define COMPILER COMPILER_INTEL
#elif defined( __GNUC__ )
# define COMPILER COMPILER_GNU
#else
# pragma error "FATAL ERROR: Unknown compiler."
#endif
// stupid warnings
#if COMPILER == COMPILER_MICROSOFT
# define _CRT_SECURE_NO_WARNINGS
# define _CRT_SECURE_NO_DEPRECATE
# pragma warning(disable: 4996)
#endif
////////////////////////////////////
// Compiler defines
////////////////////////////////////
#if COMPILER == COMPILER_MICROSOFT
#define I64FMT "%016I64X"
#define I64FMTD "%I64u"
#define I64LIT(x) (x ## i64)
#define UI64LIT(x) (x ## ui64)
#define snprintf _snprintf
#else
#define stricmp strcasecmp
#define strnicmp strncasecmp
#define I64FMT "%016llX"
#define I64FMTD "%llu"
#define I64LIT(x) (x ## LL)
#define UI64LIT(x) (x ## ULL)
#endif
#ifndef _LP64
# if defined (_M_IA64) || defined (__ia64__) || defined (_M_AMD64) || defined (__amd64) || defined(_M_X64)
# define _LP64 1
# endif
#endif
#ifdef _LP64 // to be set for 64 bit compile
# define PTRFMT "0x"I64FMT
# define SYSTEM_BITS 64
#else
# define PTRFMT "0x%X"
# define SYSTEM_BITS 32
#endif
#ifndef SIGQUIT
#define SIGQUIT 3
#endif
#if COMPILER == COMPILER_MICROSOFT
# if _MSC_VER >= 1600
# define COMPILER_NAME "VC100+"
# elif _MSC_VER >= 1500
# define COMPILER_NAME "VC90"
# elif _MSC_VER >= 1400
# define COMPILER_NAME "VC80"
# elif _MSC_VER >= 1310
# define COMPILER_NAME "VC71"
# endif
# define COMPILER_VERSION _MSC_VER
# define COMPILER_VERSION_OUT "%u"
#elif COMPILER == COMPILER_GNU
# define COMPILER_NAME "GCC"
# ifndef __GNUC_PATCHLEVEL__
# define __GNUC_PATCHLEVEL__ 0
# endif
# define COMPILER_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
# define COMPILER_VERSION_OUT "%u"
// TODO: add more compilers here when necessary
#else
# define COMPILER_NAME "unknown"
# define COMPILER_VERSION "unk"
# define COMPILER_VERSION_OUT "%s"
#endif
#if PLATFORM == PLATFORM_UNIX
# define PLATFORM_NAME "Unix"
#elif PLATFORM == PLATFORM_WIN32
# define PLATFORM_NAME "Win32"
#elif PLATFORM == PLATFORM_APPLE
# define PLATFORM_NAME "Apple"
// TODO: add more platforms here when necessary
#else
# define PLATFORM_NAME "unknown"
#endif
#if COMPILER == COMPILER_GNU
# define ATTR_NORETURN __attribute__((noreturn))
# define ATTR_PRINTF(F,V) __attribute__ ((format (printf, F, V)))
#else //COMPILER != COMPILER_GNU
# define ATTR_NORETURN
# define ATTR_PRINTF(F,V)
#endif //COMPILER == COMPILER_GNU
// taken from ACE
// have seen on some systems that both defines exist, so if that is is the case, rely on this detection here
#if (!defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN)) || (defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN))
# if defined (i386) || defined (__i386__) || defined (_M_IX86) || \
defined (vax) || defined (__alpha) || defined (__LITTLE_ENDIAN__) || \
defined (ARM) || defined (_M_IA64) || defined (__ia64__) || \
defined (_M_AMD64) || defined (__amd64)
// We know these are little endian.
# undef LITTLE_ENDIAN
# undef BIG_ENDIAN
# define LITTLE_ENDIAN 1
# define IS_LITTLE_ENDIAN 1
# define IS_BIG_ENDIAN 0
# else
// Otherwise, we assume big endian.
# undef LITTLE_ENDIAN
# undef BIG_ENDIAN
# define BIG_ENDIAN 1
# define IS_LITTLE_ENDIAN 0
# define IS_BIG_ENDIAN 1
# endif
#endif
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <string>
#include <vector>
#define ASSERT(what) { if (!(what)) { fprintf( stderr, "\n%s:%i in %s ASSERTION FAILED:\n %s\n", __FILE__, __LINE__,__FUNCTION__, #what); assert( #what &&0 ); } }
#include "LVPACommon.h"
LVPA_NAMESPACE_START
template <typename T> class AutoPtrVector
{
public:
inline AutoPtrVector(uint32 prealloc) :v(prealloc)
{
for(uint32 i = 0; i < prealloc; ++i)
v[i] = NULL;
}
inline ~AutoPtrVector()
{
for(uint32 i = 0; i < v.size(); ++i)
if(v[i])
delete v[i];
}
std::vector<T*> v;
};
LVPA_NAMESPACE_END
#endif

View file

@ -1,64 +0,0 @@
option(TTVFS_LARGEFILE_SUPPORT "Enable support for files > 4 GB? (experimental!)" FALSE)
option(TTVFS_IGNORE_CASE "Enable full case-insensitivity even on case-sensitive OSes like Linux and alike?" FALSE)
# Be sure to copy this part to your root CMakeLists.txt if you prefer to use CMake for configuring
# instead of editing the headers directly!
# If you edit the headers, this is not necessary.
if(TTVFS_LARGEFILE_SUPPORT)
add_definitions("-DVFS_LARGEFILE_SUPPORT")
endif()
if(TTVFS_IGNORE_CASE)
add_definitions("-DVFS_IGNORE_CASE")
endif()
# --snip--
# compiler specific things
if(MSVC)
# MSVC builds require installed runtime library by default
option(TTVFS_STATIC_LIB "Link as static library without runtime dependencies (Note: To get rid of this setting with MSVC, the cmake cache must be cleared)" FALSE)
add_definitions("/GR-") # run-time type info (RTTI) not required
if(TTVFS_STATIC_LIB)
# this is ugly - hackfix compiler flags
foreach(flag_var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
if(${flag_var} MATCHES "/MD")
string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
endif(${flag_var} MATCHES "/MD")
if(${flag_var} MATCHES "/MDd")
string(REGEX REPLACE "/MDd" "/MTd" ${flag_var} "${${flag_var}}")
endif(${flag_var} MATCHES "/MDd")
endforeach()
# hackfix linker flags - no idea why, but MSVC will produce linker errors otherwise
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /NODEFAULTLIB")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /NODEFAULTLIB:msvcrt.lib,msvcrtd.lib") # not sure if this is correct
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /NODEFAULTLIB:msvcrt.lib,msvcrtd.lib")
endif()
endif()
set(ttvfs_SRC
VFS.h
VFSAtomic.cpp
VFSAtomic.h
VFSDefines.h
VFSDir.cpp
VFSDir.h
VFSFile.cpp
VFSFile.h
VFSHelper.cpp
VFSHelper.h
VFSInternal.h
VFSLoader.cpp
VFSLoader.h
VFSSelfRefCounter.h
VFSTools.cpp
VFSTools.h
)
set(TTVFS_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} CACHE STRING "ttvfs include directory - for external includers" FORCE)
set(TTVFS_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE STRING "ttvfs source directory - for external includers" FORCE)
add_library(ttvfs ${ttvfs_SRC})

View file

@ -1,78 +0,0 @@
/* ttvfs -- tiny tree virtual file system
// VFS.h - all the necessary includes to get a basic VFS working
// Only include externally, not inside the library.
See VFSDefines.h for compile configration.
---------[ License ]----------
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef TTVFS_VFS_H
#define TTVFS_VFS_H
#include "VFSDefines.h"
VFS_NAMESPACE_START
bool _checkCompatInternal(bool large, bool nocase, unsigned int vfspos_size);
/** It is recommended to call this function early in your code
and ensure it returns true - if it does not, compiler settings
are inconsistent, which may cause otherwise hard to detect problems. */
inline static bool checkCompat(void)
{
#ifdef VFS_LARGEFILE_SUPPORT
bool largefile = true;
#else
bool largefile = false;
#endif
#ifdef VFS_IGNORE_CASE
bool nocase = true;
#else
bool nocase = false;
#endif
return _checkCompatInternal(largefile, nocase, sizeof(vfspos));
}
VFS_NAMESPACE_END
#include <cstring>
#include <string>
#include "VFSHelper.h"
#include "VFSFile.h"
#include "VFSDir.h"
// Checks to enforce correct including.
// At least on windows, <string> includes <cstdio>,
// but that must be included after "VFSInternal.h",
// and "VFSInternal.h" may only be used inside the library (or by extensions),
// because it redefines fseek and ftell, which would
// mess up the ABI if included elsewhere.
#ifdef VFS_INTERNAL_H
#error Oops, VFS_INTERNAL_H is defined, someone messed up and included VFSInternal.h wrongly.
#endif
#endif

View file

@ -1,103 +0,0 @@
// VFSAtomic.cpp - atomic operations and thread locking
// For conditions of distribution and use, see copyright notice in VFS.h
/** --- Atomic operations and thread safety ---
* You may want to add your own implementation if thread safety is needed.
* If not, just leave everything like it is.
* If you are on windows, Interlocked[In/De]crement is faster than
explicit mutex locking for integer operations.
* TODO: The actual locking that is done in the tree when VFS_THREADSAFE is defined
is rather crude for the time beeing; a somewhat more efficient ReadWriteLock
implementation would be nice to have, someday.
* If you can, leave VFS_THREADSAFE undefined and do the locking externally,
it will probably have much better performance than if each and every operation
does a lock and unlock call.
(For a rather I/O based library this should not really make a difference, anyway.
But don't say you haven't been warned :) )
*/
#include "VFSInternal.h"
#include "VFSAtomic.h"
// for Interlocked[In/De]crement, if required
#if defined(_WIN32) && defined(VFS_THREADSAFE)
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
#endif
VFS_NAMESPACE_START
#ifdef VFS_THREADSAFE
static Mutex mtx;
#endif
int Atomic_Incr(volatile int &i)
{
#ifdef VFS_THREADSAFE
# ifdef _WIN32
volatile LONG* dp = (volatile LONG*) &i;
return InterlockedIncrement( dp );
# else
Guard g(mtx);
# endif
#endif
return ++i;
}
int Atomic_Decr(volatile int &i)
{
#ifdef VFS_THREADSAFE
# ifdef _WIN32
volatile LONG* dp = (volatile LONG*) &i;
return InterlockedDecrement( dp );
# else
Guard g(mtx);
# endif
#endif
return --i;
}
/* Implement your Mutex class here.
Important: The mutex must be re-entrant/recursive,
means it must be possible to lock it from the same thread multiple times.
*/
Mutex::Mutex()
{
// implement your own if needed. Remove the trap below when you are done.
// This is to prevent people from defining VFS_THREADSAFE and expecting everything to work just like that :)
#ifdef VFS_THREADSAFE
#error VFSAtomic: Hey, you forgot to implement the mutex class, cant guarantee thread safety! Either undef VFS_THREADSAFE or read the docs and get your hands dirty.
#endif
}
Mutex::~Mutex()
{
// implement your own if needed
}
void Mutex::Lock(void)
{
// implement your own if needed
}
void Mutex::Unlock(void)
{
// implement your own if needed
}
Guard::Guard(Mutex& m)
: _m(m)
{
_m.Lock();
}
Guard::~Guard()
{
_m.Unlock();
}
VFS_NAMESPACE_END

View file

@ -1,39 +0,0 @@
// VFSAtomic.h - atomic operations and thread locking
// For conditions of distribution and use, see copyright notice in VFS.h
#ifndef VFS_ATOMIC_H
#define VFS_ATOMIC_H
#include "VFSDefines.h"
VFS_NAMESPACE_START
int Atomic_Incr(volatile int &i);
int Atomic_Decr(volatile int &i);
// generic Mutex class, needs to be reentrant/recursive.
class Mutex
{
public:
Mutex();
~Mutex();
void Lock();
void Unlock();
protected:
// add own stuff if needed
};
class Guard
{
public:
Guard(Mutex& m);
~Guard();
protected:
Mutex& _m;
};
VFS_NAMESPACE_END
#endif

View file

@ -1,79 +0,0 @@
// VFSDefines.h - compile config and basic setup
// For conditions of distribution and use, see copyright notice in VFS.h
#ifndef VFS_DEFINES_H
#define VFS_DEFINES_H
/* --- Config section -- modify as needed --- */
// choose a namespace name, or comment out to disable namespacing completely (not recommended)
#define VFS_NAMESPACE ttvfs
// Define this to allow dealing with files > 4 GB, using non-standard functions.
// This may or may not work with your platform/compiler, good luck.
//#define VFS_LARGEFILE_SUPPORT
// Define this to make all operations case insensitive.
// Windows systems generally don't care much, but for Linux and Mac this can be used
// to get the same behavior as on windows.
// Additionally, this achieves full case insensitivity within the library,
// if the the same files are accessed multiple times by the program, but with not-uniform case.
// (no sane programmer should do this, anyway).
// However, on non-windows systems this will decrease performance when checking for files
// on disk (see VFSLoader.cpp).
#define VFS_IGNORE_CASE
// Define this to make all VFSFile, VFSDir, VFSHelper operations thread-safe.
// If you do, do not forget to add your own implementation to VFSAtomic.cpp/.h !
// If this is not defined, you can still do manual locking if you know what you're doing,
// performance matters, and you implemented actual locking into the Mutex class.
// If no Mutex implementation is provided, its operations are no-ops, beware!
//#define VFS_THREADSAFE
/* --- End of config section --- */
#ifdef VFS_NAMESPACE
# define VFS_NAMESPACE_START namespace VFS_NAMESPACE {
# define VFS_NAMESPACE_END }
# define VFS_NAMESPACE_IMPL VFS_NAMESPACE::
#else
# define VFS_NAMESPACE_START
# define VFS_NAMESPACE_END
# define VFS_NAMESPACE_IMPL
#endif
VFS_NAMESPACE_START
#ifdef VFS_LARGEFILE_SUPPORT
# if defined(_MSC_VER)
typedef __int64 vfspos;
# else
typedef long long vfspos;
# endif
#else
typedef unsigned int vfspos;
#endif
// simple guard wrapper, works also if VFS_THREADSAFE is not defined
#define VFS_GUARD(obj) VFS_NAMESPACE_IMPL Guard __vfs_stack_guard((obj)->mutex())
// defines for optional auto-locking; only if VFS_THREADSAFE is defined
#ifdef VFS_THREADSAFE
# define VFS_GUARD_OPT(obj) VFS_GUARD(obj)
#else
# define VFS_GUARD_OPT(obj)
#endif
#if defined(_MSC_VER)
# define VFS_STRICMP stricmp
#else
# define VFS_STRICMP strcasecmp
#endif
static const vfspos npos = vfspos(-1);
VFS_NAMESPACE_END
#endif

View file

@ -1,255 +0,0 @@
// VFSDir.cpp - basic directory interface + classes
// For conditions of distribution and use, see copyright notice in VFS.h
#include "VFSInternal.h"
#include "VFSTools.h"
#include "VFSFile.h"
#include "VFSDir.h"
VFS_NAMESPACE_START
VFSDir::VFSDir()
: ref(this), _name(NULL)
{
}
VFSDir::VFSDir(const char *fullpath)
: ref(this)
{
_setFullName(fullpath);
}
VFSDir::~VFSDir()
{
for(Files::iterator it = _files.begin(); it != _files.end(); it++)
it->second->ref--;
for(Dirs::iterator it = _subdirs.begin(); it != _subdirs.end(); it++)
it->second->ref--;
}
void VFSDir::_setFullName(const char *fullname)
{
_fullname = FixPath(fullname);
_name = PathToFileName(_fullname.c_str());
}
VFSDir *VFSDir::createNew(void) const
{
return new VFSDir;
}
unsigned int VFSDir::load(const char *dir /* = NULL */)
{
return 0;
}
bool VFSDir::add(VFSFile *f, bool overwrite /* = true */)
{
if(!f)
return false;
VFS_GUARD_OPT(this);
Files::iterator it = _files.find(f->name());
if(it != _files.end())
{
if(overwrite)
{
VFSFile *oldf = it->second;
if(oldf == f)
return false;
oldf->ref--;
_files.erase(it);
}
else
return false;
}
f->ref++;
_files[f->name()] = f;
return true;
}
bool VFSDir::addRecursive(VFSFile *f, bool overwrite /* = true */)
{
if(!f)
return false;
VFS_GUARD_OPT(this);
// figure out directory from full file name
std::string dirname(f->fullname());
size_t pathend = dirname.find_last_of("/\\");
VFSDir *vdir;
if(pathend != std::string::npos)
{
dirname = dirname.substr(0, pathend);
vdir = getDir(dirname.c_str(), true);
}
else
vdir = this;
return vdir->add(f, true);
}
bool VFSDir::merge(VFSDir *dir, bool overwrite /* = true */)
{
if(!dir)
return false;
bool result = false;
VFS_GUARD_OPT(this);
for(Files::iterator it = dir->_files.begin(); it != dir->_files.end(); it++)
result = add(it->second, overwrite) || result;
for(Dirs::iterator it = dir->_subdirs.begin(); it != dir->_subdirs.end(); it++)
result = insert(it->second, overwrite) || result;
return result;
}
bool VFSDir::insert(VFSDir *subdir, bool overwrite /* = true */)
{
if(!subdir)
return false;
VFS_GUARD_OPT(this);
Dirs::iterator it = _subdirs.find(subdir->name());
VFSDir *mydir;
if(it != _subdirs.end())
{
mydir = it->second;
//return it->second->merge(subdir, overwrite);
}
else
{
// create a new subtree, not to pollute the original one with data that may be added later
mydir = subdir->createNew(); // create subdir of same type
mydir->_setFullName(subdir->fullname());
_subdirs[mydir->name()] = mydir;
}
return mydir->merge(subdir, overwrite);
}
VFSFile *VFSDir::getFile(const char *fn)
{
char *slashpos = (char *)strchr(fn, '/');
// if there is a '/' in the string, descend into subdir and continue there
if(slashpos)
{
const char *sub = slashpos + 1;
std::string t(fn, slashpos - fn);
VFS_GUARD_OPT(this);
VFSDir *subdir = getDir(t.c_str()); // fn is null-terminated early here
return subdir ? subdir->getFile(sub) : NULL;
}
// no subdir? file must be in this dir now.
VFS_GUARD_OPT(this);
Files::iterator it = _files.find(fn);
return it != _files.end() ? it->second : NULL;
}
VFSDir *VFSDir::getDir(const char *subdir, bool forceCreate /* = false */)
{
if(!subdir[0] || (subdir[0] == '.' && (!subdir[1] || subdir[1] == '/'))) // empty string or "." or "./" ? use this.
return this;
VFSDir *ret = NULL;
char *slashpos = (char *)strchr(subdir, '/');
// if there is a '/' in the string, descend into subdir and continue there
if(slashpos)
{
const char *sub = slashpos + 1;
std::string t(subdir, slashpos - subdir);
VFS_GUARD_OPT(this);
Dirs::iterator it = _subdirs.find(t);
if(it != _subdirs.end())
{
ret = it->second->getDir(sub, forceCreate); // descend into subdirs
}
else if(forceCreate)
{
VFSDir *ins = createNew();
std::string newname(fullname());
newname += '/';
newname += t;
ins->_setFullName(newname.c_str());
_subdirs[ins->name()] = ins;
ret = ins->getDir(sub, true); // create remaining structure
}
}
else
{
VFS_GUARD_OPT(this);
Dirs::iterator it = _subdirs.find(subdir);
if(it != _subdirs.end())
ret = it->second;
else if(forceCreate)
{
ret = createNew();
std::string newname(fullname());
newname += '/';
newname += subdir;
ret->_setFullName(newname.c_str());
_subdirs[ret->name()] = ret;
}
}
return ret;
}
// ----- VFSDirReal start here -----
VFSDirReal::VFSDirReal() : VFSDir()
{
}
VFSDir *VFSDirReal::createNew(void) const
{
return new VFSDirReal;
}
unsigned int VFSDirReal::load(const char *dir /* = NULL */)
{
VFS_GUARD_OPT(this);
if(dir)
_setFullName(dir);
StringList li;
GetFileList(_fullname.c_str(), li);
for(StringList::iterator it = li.begin(); it != li.end(); it++)
{
if(VFSFile *oldf = getFile(it->c_str()))
oldf->ref--;
VFSFileReal *f = new VFSFileReal((_fullname + '/' + *it).c_str());
_files[f->name()] = f;
}
unsigned int sum = li.size();
li.clear();
GetDirList(_fullname.c_str(), li, false);
for(std::deque<std::string>::iterator it = li.begin(); it != li.end(); it++)
{
if(VFSDir *oldd = getDir(it->c_str()))
oldd->ref--;
VFSDir *d = createNew();
std::string full(_fullname);
full += '/';
full += *it;
sum += d->load(full.c_str()); // GetDirList() always returns relative paths
_subdirs[d->name()] = d;
}
return sum;
}
VFS_NAMESPACE_END

View file

@ -1,118 +0,0 @@
// VFSDir.h - basic directory interface + classes
// For conditions of distribution and use, see copyright notice in VFS.h
#ifndef VFSDIR_H
#define VFSDIR_H
#include "VFSDefines.h"
#include <map>
#include "VFSSelfRefCounter.h"
VFS_NAMESPACE_START
#ifdef VFS_IGNORE_CASE
# ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable: 4996)
# endif
struct ci_less
{
inline bool operator() (const std::string& a, const std::string& b) const
{
return VFS_STRICMP(a.c_str(), b.c_str()) < 0;
}
};
# ifdef _MSC_VER
# pragma warning(pop)
# endif
#endif
class VFSDir;
class VFSFile;
class VFSDir
{
public:
#ifdef VFS_IGNORE_CASE
typedef std::map<std::string, VFSDir*, ci_less> Dirs;
typedef std::map<std::string, VFSFile*, ci_less> Files;
#else
typedef std::map<std::string, VFSDir*> Dirs;
typedef std::map<std::string, VFSFile*> Files;
#endif
VFSDir();
VFSDir(const char *fullpath);
virtual ~VFSDir();
/* Load directory with given path. If dir is NULL, reload previously loaded directory.
If there is no previously loaded directory, load root. */
virtual unsigned int load(const char *dir = NULL);
virtual VFSFile *getFile(const char *fn);
virtual VFSDir *getDir(const char *subdir, bool forceCreate = false);
virtual VFSDir *createNew(void) const;
virtual const char *getType(void) const { return "VFSDir"; }
bool insert(VFSDir *subdir, bool overwrite = true);
bool merge(VFSDir *dir, bool overwrite = true);
bool add(VFSFile *f, bool overwrite = true); // add file directly in this dir
bool addRecursive(VFSFile *f, bool overwrite = true); // traverse subdir tree to find correct subdir; create if not existing
inline const char *name() const { VFS_GUARD_OPT(this); return _name; }
inline const char *fullname() const { VFS_GUARD_OPT(this); return _fullname.c_str(); }
// iterators are NOT thread-safe! If you need to iterate over things in a multithreaded environment,
// do the locking yourself! (see below)
inline Files::iterator fileIter() { return _files.begin(); }
inline Files::iterator fileIterEnd() { return _files.end(); }
inline Dirs::iterator dirIter() { return _subdirs.begin(); }
inline Dirs::iterator dirIterEnd() { return _subdirs.end(); }
inline Files::const_iterator fileIter() const { return _files.begin(); }
inline Files::const_iterator fileIterEnd() const { return _files.end(); }
inline Dirs::const_iterator dirIter() const { return _subdirs.begin(); }
inline Dirs::const_iterator dirIterEnd() const { return _subdirs.end(); }
// std::map<std::string,*> stores for files and subdirs
Files _files;
Dirs _subdirs;
// reference counter, does auto-delete holder when it reaches 0. initially 1.
SelfRefCounter<VFSDir> ref;
// the following functions should be used before and after an iteration finishes
// alternatively, VFS_GUARD(dir) can be used to create a locking guard on the stack.
inline void lock() { _mtx.Lock(); }
inline void unlock() { _mtx.Unlock(); }
inline Mutex& mutex() const { return _mtx; }
protected:
void _setFullName(const char *fullname);
std::string _fullname;
const char *_name; // must point to an address constant during object lifetime (like _fullname.c_str() + N)
// (not necessary to have an additional string copy here, just wastes memory)
mutable Mutex _mtx;
};
typedef VFSDir::Files::iterator FileIter;
typedef VFSDir::Dirs::iterator DirIter;
typedef VFSDir::Files::const_iterator ConstFileIter;
typedef VFSDir::Dirs::const_iterator ConstDirIter;
class VFSDirReal : public VFSDir
{
public:
VFSDirReal();
virtual ~VFSDirReal() {};
virtual unsigned int load(const char *dir = NULL);
virtual VFSDir *createNew(void) const;
virtual const char *getType(void) const { return "VFSDirReal"; }
};
VFS_NAMESPACE_END
#endif

View file

@ -1,258 +0,0 @@
// VFSFile.cpp - basic file interface + classes
// For conditions of distribution and use, see copyright notice in VFS.h
#include "VFSInternal.h"
#include "VFSFile.h"
#include "VFSTools.h"
VFS_NAMESPACE_START
VFSFile::VFSFile()
: ref(this)
{
}
VFSFileReal::VFSFileReal(const char *name /* = NULL */)
: VFSFile()
{
_buf = NULL;
_setName(name);
_fh = NULL;
_size = npos;
}
VFSFileReal::~VFSFileReal()
{
close();
dropBuf(true);
}
// call this only with a lock held!
void VFSFileReal::_setName(const char *n)
{
if(n && *n)
{
_fullname = FixPath(n);
_name = PathToFileName(_fullname.c_str());
}
}
bool VFSFileReal::open(const char *fn /* = NULL */, const char *mode /* = NULL */)
{
VFS_GUARD_OPT(this);
if(isopen())
close();
dropBuf(true);
_setName(fn);
_fh = fopen(_fullname.c_str(), mode ? mode : "rb");
if(!_fh)
return false;
fseek((FILE*)_fh, 0, SEEK_END);
_size = getpos();
fseek((FILE*)_fh, 0, SEEK_SET);
return true;
}
bool VFSFileReal::isopen(void) const
{
VFS_GUARD_OPT(this);
return !!_fh;
}
bool VFSFileReal::iseof(void) const
{
VFS_GUARD_OPT(this);
return !_fh || feof((FILE*)_fh);
}
const char *VFSFileReal::name(void) const
{
VFS_GUARD_OPT(this);
return _name;
}
const char *VFSFileReal::fullname(void) const
{
VFS_GUARD_OPT(this);
return _fullname.c_str();
}
bool VFSFileReal::close(void)
{
VFS_GUARD_OPT(this);
if(_fh)
{
fclose((FILE*)_fh);
_fh = NULL;
}
return true;
}
bool VFSFileReal::seek(vfspos pos)
{
VFS_GUARD_OPT(this);
if(!_fh)
return false;
fseek((FILE*)_fh, pos, SEEK_SET);
return true;
}
bool VFSFileReal::seekRel(vfspos offs)
{
VFS_GUARD_OPT(this);
if(!_fh)
return false;
fseek((FILE*)_fh, offs, SEEK_CUR);
return true;
}
bool VFSFileReal::flush(void)
{
VFS_GUARD_OPT(this);
if(_fh)
return false;
fflush((FILE*)_fh);
return true;
}
vfspos VFSFileReal::getpos(void) const
{
VFS_GUARD_OPT(this);
if(!_fh)
return npos;
return ftell((FILE*)_fh);
}
unsigned int VFSFileReal::read(void *dst, unsigned int bytes)
{
VFS_GUARD_OPT(this);
if(!_fh)
return npos;
return fread(dst, 1, bytes, (FILE*)_fh);
}
unsigned int VFSFileReal::write(const void *src, unsigned int bytes)
{
VFS_GUARD_OPT(this);
if(!_fh)
return npos;
return fwrite(src, 1, bytes, (FILE*)_fh);
}
vfspos VFSFileReal::size(void)
{
VFS_GUARD_OPT(this);
if(_size != npos)
return _size;
open();
close();
// now size is known.
return _size;
}
const void *VFSFileReal::getBuf(void)
{
VFS_GUARD_OPT(this);
if(_buf)
return _buf;
bool op = isopen();
if(!op && !open()) // open with default params if not open
return NULL;
unsigned int s = (unsigned int)size();
_buf = malloc(s + 4); // a bit extra padding
if(!_buf)
return NULL;
if(op)
{
vfspos oldpos = getpos();
seek(0);
unsigned int offs = read(_buf, s);
memset((char*)_buf + offs, 0, 4);
seek(oldpos);
}
else
{
unsigned int offs = read(_buf, s);
memset((char*)_buf + offs, 0, 4);
close();
}
return _buf;
}
void VFSFileReal::dropBuf(bool del)
{
VFS_GUARD_OPT(this);
if(del && _buf)
free(_buf);
_buf = NULL;
}
// ------------- VFSFileMem -----------------------
VFSFileMem::VFSFileMem(const char *name, void *buf, unsigned int size, Mode mode /* = COPY */, delete_func delfunc /* = NULL */)
: VFSFile(), _pos(0), _size(size), _buf(buf), _delfunc(delfunc), _mybuf(mode == TAKE_OVER || mode == COPY)
{
_setName(name);
if(mode == COPY)
{
_buf = malloc(size+1);
_delfunc = free;
memcpy(_buf, buf, size);
((char*)_buf)[size] = 0;
}
}
VFSFileMem::~VFSFileMem()
{
if(_mybuf)
{
if(_delfunc)
_delfunc(_buf);
else
delete [] (char*)_buf;
}
}
void VFSFileMem::_setName(const char *n)
{
if(n && *n)
{
_fullname = FixPath(n);
_name = PathToFileName(_fullname.c_str());
}
}
unsigned int VFSFileMem::read(void *dst, unsigned int bytes)
{
VFS_GUARD_OPT(this);
if(iseof())
return 0;
unsigned int rem = std::min<unsigned int>((unsigned int)(_size - _pos), bytes);
memcpy(dst, (char*)_buf + _pos, rem);
return rem;
}
unsigned int VFSFileMem::write(const void *src, unsigned int bytes)
{
VFS_GUARD_OPT(this);
if(iseof())
return 0;
unsigned int rem = std::min<unsigned int>((unsigned int)(_size - _pos), bytes);
memcpy((char*)_buf + _pos, src, rem);
return rem;
}
VFS_NAMESPACE_END

View file

@ -1,183 +0,0 @@
// VFSFile.h - basic file interface + classes
// For conditions of distribution and use, see copyright notice in VFS.h
#ifndef VFSFILE_H
#define VFSFILE_H
#include "VFSDefines.h"
#include "VFSSelfRefCounter.h"
#include <string>
VFS_NAMESPACE_START
/** -- VFSFile basic interface --
* All functions that return bool should return true on success and false on failure.
* If an operation is not necessary or irrelevant (for example, files in memory can't be closed),
* it is useful to return true anyways, because this operation did not fail, technically.
* (Common sense here!)
* An int/vfspos value of 0 indicates failure, except the size/seek/getpos functions, where npos means failure.
* Only the functions required or applicable need to be implemented, for unsupported operations
* the default implementation should be sufficient.
**/
class VFSFile
{
public:
/** The ctor is expected to set both name() and fullname(). */
VFSFile();
virtual ~VFSFile() {};
/** Open a file. If fn is NULL (the default), open fullname().
Mode can be "r", "w", "rb", "rb", and possibly other things that fopen supports.
It is the subclass's choice to support other modes. Default is "rb". */
virtual bool open(const char *fn = NULL, const char *mode = NULL) { return false; }
virtual bool isopen(void) const { return false; }
virtual bool iseof(void) const { return true; }
/** Returns the plain file name. Never NULL. */
virtual const char *name(void) const { return ""; }
/** Returns the file name with full path. Never NULL. */
virtual const char *fullname(void) const { return ""; }
virtual bool close(void) { return true; }
virtual bool seek(vfspos pos) { return false; }
/** Seek relative to current position. Negative numbers will seek backwards.
(In most cases, the default implementation does not have to be changed) */
virtual bool seekRel(vfspos offs) { VFS_GUARD_OPT(this); return seek(getpos() + offs); }
virtual bool flush(void) { return true; }
/** Current offset in file. Return npos if NA. */
virtual vfspos getpos(void) const { return npos; }
virtual unsigned int read(void *dst, unsigned int bytes) { return 0; }
virtual unsigned int write(const void *src, unsigned int bytes) { return 0; }
/** Return file size. If NA, return npos. If size is not yet known,
open() and close() may be called (with default args) to find out the size.
The file is supposed to be in its old state when the function returns,
that is in the same open state and seek position.
The pointer returned by getBuf() must not change. */
virtual vfspos size(void) { return npos; }
/** Attempt to increase file size. Returns new size after completion.
May return any size. Failure is indicated by a size() that didn't change. */
virtual vfspos size(vfspos newsize) { return size(); }
/** Return full file content in memory. Like size(), this may do other operations on the file,
but after the function returns the file is expected to be in the same state it was before.
If the file is not open before the call, it will be opened with default parameters (that is, "rb").
Addition EOL mangling my happen if the file is opened in text mode before (= not binary).
Calls to open() should delete this memory if the file was previously opened in a different mode.
The returned memory is not guaranteed to be writable without problems, so don't do it.
Don't cast the const away. You have been warned.
This memory can be freed with free(), after calling dropBuf(false). */
virtual const void *getBuf(void) { return NULL; }
/** If del is true, delete internal buffer. If false, unregister internal buffer from the file,
but do not delete. Use free() later. */
virtual void dropBuf(bool del) {}
/** Basic RTTI, for debugging purposes */
virtual const char *getType(void) const { return "<BASE>"; }
/** Reference count, if the pointer to this file is stored somewhere it is advisable to increase
(ref++) it. If it reaches 0, this file is deleted automatically. */
SelfRefCounter<VFSFile> ref;
inline void lock() { _mtx.Lock(); }
inline void unlock() { _mtx.Unlock(); }
inline Mutex& mutex() const { return _mtx; }
protected:
mutable Mutex _mtx;
};
class VFSFileReal : public VFSFile
{
public:
VFSFileReal(const char *name = NULL);
virtual ~VFSFileReal();
virtual bool open(const char *fn = NULL, const char *mode = NULL);
virtual bool isopen(void) const;
virtual bool iseof(void) const;
virtual const char *name(void) const;
virtual const char *fullname(void) const;
virtual bool close(void);
virtual bool seek(vfspos pos);
virtual bool seekRel(vfspos offs);
virtual bool flush(void);
virtual vfspos getpos(void) const;
virtual unsigned int read(void *dst, unsigned int bytes);
virtual unsigned int write(const void *src, unsigned int bytes);
virtual vfspos size(void);
virtual const void *getBuf(void);
virtual void dropBuf(bool del);
virtual const char *getType(void) const { return "disk"; }
inline void *getFP() { return _fh; }
protected:
void _setName(const char *n);
std::string _fullname;
const char *_name;
void *_fh; // FILE*
vfspos _size;
void *_buf;
};
class VFSFileMem : public VFSFile
{
public:
enum Mode
{
COPY, //- Make a copy of the buffer (default action).
REUSE, //- Use the passed-in buffer as is. Requires the pointer
// to remain valid over the life of this object.
TAKE_OVER, //- Take over the passed-in buffer; it will be deleted on object destruction.
};
typedef void (*delete_func)(void*);
/* Creates a virtual file from a memory buffer. By default, the memory is copied.
A deletor function can be passed optionally, if its NULL (the default),
delete[] (char*)buf will be used. For malloc()'d memory, pass free. (Only used if mode is TAKE_OVER) */
VFSFileMem(const char *name, void *buf, unsigned int size, Mode m = COPY, delete_func delfunc = NULL);
virtual ~VFSFileMem();
virtual bool open(const char *fn = NULL, const char *mode = NULL) { return true; }
virtual bool isopen(void) const { return true; } // always open
virtual bool iseof(void) const { VFS_GUARD_OPT(this); return _pos >= _size; }
virtual const char *name(void) const { VFS_GUARD_OPT(this); return _name; }
virtual const char *fullname(void) const { VFS_GUARD_OPT(this); return _fullname.c_str(); }
virtual bool close(void) { return true; } // cant close, but not a problem
virtual bool seek(vfspos pos) { VFS_GUARD_OPT(this); _pos = pos; return true; }
virtual bool seekRel(vfspos offs) { VFS_GUARD_OPT(this); _pos += offs; return true; }
virtual bool flush(void) { return false; } // can't flush, if a successful file write is expected, this IS a problem.
virtual vfspos getpos(void) const { VFS_GUARD_OPT(this); return _pos; }
virtual unsigned int read(void *dst, unsigned int bytes);
virtual unsigned int write(const void *src, unsigned int bytes);
virtual vfspos size(void) { VFS_GUARD_OPT(this); return _size; }
virtual const void *getBuf(void) { VFS_GUARD_OPT(this); return _buf; }
virtual void dropBuf(bool) {} // we can't simply drop the internal buffer, as the file is entirely memory based
virtual const char *getSource(void) const { return "mem"; }
protected:
void _setName(const char *n);
std::string _fullname;
const char *_name;
vfspos _pos;
vfspos _size;
void *_buf;
delete_func _delfunc;
bool _mybuf;
};
VFS_NAMESPACE_END
#endif

View file

@ -1,350 +0,0 @@
// VFSHelper.cpp - glues it all together and makes use simple
// For conditions of distribution and use, see copyright notice in VFS.h
#include <iostream> // for debug only, see EOF
#include "VFSInternal.h"
#include "VFSHelper.h"
#include "VFSAtomic.h"
#include "VFSTools.h"
#include "VFSDir.h"
#include "VFSFile.h"
#include "VFSLoader.h"
#ifdef _DEBUG
# include <cassert>
# define DEBUG_ASSERT(x) assert(x)
#else
# define DEBUG_ASSERT(x)
#endif
VFS_NAMESPACE_START
// predecl is in VFS.h
bool _checkCompatInternal(bool large, bool nocase, unsigned int vfspos_size)
{
#ifdef VFS_LARGEFILE_SUPPORT
bool largefile_i = true;
#else
bool largefile_i = false;
#endif
#ifdef VFS_IGNORE_CASE
bool nocase_i = true;
#else
bool nocase_i = false;
#endif
return (large == largefile_i)
&& (nocase == nocase_i)
&& (sizeof(vfspos) == vfspos_size);
}
VFSHelper::VFSHelper()
: filesysRoot(NULL), merged(NULL)
{
_ldrDiskId = _AddFixedLoader(); // NULL intentionally. created by LoadFileSysRoot()
}
VFSHelper::~VFSHelper()
{
Clear();
}
void VFSHelper::Clear(void)
{
VFS_GUARD_OPT(this);
_cleanup();
if(filesysRoot)
{
filesysRoot->ref--; // this should always delete it...
filesysRoot = NULL; // ...but it may be referenced elsewhere, just in case
}
for(unsigned int i = 0; i < preRoot.size(); ++i)
preRoot[i]->ref--;
preRoot.clear();
for(unsigned int i = 0; i < postRoot.size(); ++i)
postRoot[i]->ref--;
postRoot.clear();
for(unsigned int i = 0; i < FixedLoadersCount(); ++i)
if(fixedLdrs[i])
{
delete fixedLdrs[i];
fixedLdrs[i] = NULL;
}
}
unsigned int VFSHelper::_AddFixedLoader(VFSLoader *ldr /* = NULL */)
{
fixedLdrs.push_back(ldr);
return FixedLoadersCount() - 1;
}
void VFSHelper::_cleanup(void)
{
VFS_GUARD_OPT(this); // be extra safe and ensure this is locked
if(merged)
{
merged->ref--;
merged = NULL;
}
for(VFSMountList::iterator it = vlist.begin(); it != vlist.end(); ++it)
it->vdir->ref--;
vlist.clear();
for(LoaderList::iterator it = dynLdrs.begin(); it != dynLdrs.end(); ++it)
delete *it;
dynLdrs.clear();
}
bool VFSHelper::LoadFileSysRoot(void)
{
VFS_GUARD_OPT(this);
VFSDirReal *oldroot = filesysRoot;
filesysRoot = new VFSDirReal;
if(!filesysRoot->load("."))
{
filesysRoot->ref--;
filesysRoot = oldroot;
return false;
}
if(!fixedLdrs[_ldrDiskId])
fixedLdrs[_ldrDiskId] = new VFSLoaderDisk;
if(oldroot)
oldroot->ref--;
return true;
}
void VFSHelper::Prepare(bool clear /* = true */)
{
VFS_GUARD_OPT(this);
if(clear)
_cleanup();
if(!merged)
{
merged = new VFSDir("");
}
for(size_t i = 0; i < preRoot.size(); ++i)
merged->merge(preRoot[i]);
if(filesysRoot)
merged->merge(filesysRoot);
for(size_t i = 0; i < postRoot.size(); ++i)
merged->merge(postRoot[i]);
}
void VFSHelper::Reload(bool fromDisk /* = false */)
{
VFS_GUARD_OPT(this);
if(fromDisk)
LoadFileSysRoot();
Prepare(false);
for(VFSMountList::iterator it = vlist.begin(); it != vlist.end(); it++)
GetDir(it->mountPoint.c_str(), true)->merge(it->vdir, it->overwrite);
}
bool VFSHelper::Mount(const char *src, const char *dest, bool overwrite /* = true*/)
{
VFS_GUARD_OPT(this);
return AddVFSDir(GetDir(src, false), dest, overwrite);
}
bool VFSHelper::AddVFSDir(VFSDir *dir, const char *subdir /* = NULL */, bool overwrite /* = true */)
{
if(!dir)
return false;
VFS_GUARD_OPT(this);
if(!subdir)
subdir = dir->fullname();
VFSDir *sd = GetDir(subdir, true);
if(!sd) // may be NULL if Prepare() was not called before
return false;
dir->ref++; // because this is to be added to vlist
VDirEntry ve(dir, subdir, overwrite);
_StoreMountPoint(ve);
sd->merge(dir, overwrite); // merge into specified subdir. will be (virtually) created if not existing
return true;
}
bool VFSHelper::Unmount(const char *src, const char *dest)
{
VFSDir *vd = GetDir(src, false);
if(!vd)
return false;
VDirEntry ve(vd, dest, true); // last is dummy
if(!_RemoveMountPoint(ve))
return false;
Reload(false);
return true;
}
void VFSHelper::_StoreMountPoint(const VDirEntry& ve)
{
// scan through and ensure only one mount point with the same data is present.
// if present, remove and re-add, this ensures the mount point is at the end of the list
for(VFSMountList::iterator it = vlist.begin(); it != vlist.end(); )
{
const VDirEntry& oe = *it;
if(ve.mountPoint == oe.mountPoint && ve.vdir == oe.vdir
&& (ve.overwrite || !oe.overwrite) ) // overwrite definitely, or if other does not overwrite
{
it = vlist.erase(it); // do not break; just in case there are more (fixme?)
}
else
++it;
}
vlist.push_back(ve);
}
bool VFSHelper::_RemoveMountPoint(const VDirEntry& ve)
{
for(VFSMountList::iterator it = vlist.begin(); it != vlist.end(); ++it)
{
const VDirEntry& oe = *it;
if(ve.mountPoint == oe.mountPoint && ve.vdir == oe.vdir)
{
vlist.erase(it);
return true;
}
}
return false;
}
bool VFSHelper::MountExternalPath(const char *path, const char *where /* = "" */)
{
// no guard required here, AddVFSDir has one, and the reference count is locked as well.
VFSDirReal *vfs = new VFSDirReal;
if(vfs->load(path))
AddVFSDir(vfs, where);
return !!--(vfs->ref); // 0 if deleted
}
void VFSHelper::AddLoader(VFSLoader *ldr)
{
VFS_GUARD_OPT(this);
dynLdrs.push_back(ldr);
}
inline static VFSFile *VFSHelper_GetFileByLoader(VFSLoader *ldr, const char *fn, VFSDir *root)
{
if(!ldr)
return NULL;
VFSFile *vf = ldr->Load(fn);
if(vf)
{
root->addRecursive(vf, true);
--(vf->ref);
}
return vf;
}
VFSFile *VFSHelper::GetFile(const char *fn)
{
while(fn[0] == '.' && fn[1] == '/')
fn += 2;
VFSFile *vf = NULL;
// guarded block
{
VFS_GUARD_OPT(this);
if(!merged) // Prepare() called?
return NULL;
vf = merged->getFile(fn);
}
// nothing found? maybe a loader has something.
// if so, add the newly created VFSFile to the tree.
// constant, no locking required here - also a bad idea in case a loader does heavy I/O
if(!vf)
for(unsigned int i = 0; i < fixedLdrs.size(); ++i)
if((vf = VFSHelper_GetFileByLoader(fixedLdrs[i], fn, GetDirRoot())))
break;
if(!vf)
{
VFS_GUARD_OPT(this);
for(LoaderList::iterator it = dynLdrs.begin(); it != dynLdrs.end(); ++it)
if((vf = VFSHelper_GetFileByLoader(*it, fn, GetDirRoot())))
break;
}
//printf("VFS: GetFile '%s' -> '%s' (%p)\n", fn, vf ? vf->fullname() : "NULL", vf);
return vf;
}
VFSDir *VFSHelper::GetDir(const char* dn, bool create /* = false */)
{
while(dn[0] == '.' && dn[1] == '/')
dn += 2;
VFS_GUARD_OPT(this);
return (merged && *dn) ? merged->getDir(dn, create) : merged;
}
VFSDir *VFSHelper::GetDirRoot(void)
{
VFS_GUARD_OPT(this);
return merged;
}
// DEBUG STUFF
static void _DumpTreeRecursive(std::ostream& os, VFSDir *vd, const std::string& sp, VFSDir *parent)
{
std::string sub = sp + " ";
os << sp << "d|" << vd->name() << " [" << vd->getType() << ", ref " << vd->ref.count() << ", 0x" << vd << "]";
if(parent && strncmp(parent->fullname(), vd->fullname(), strlen(parent->fullname())))
os << " <-- {" << vd->fullname() << "} ***********";
os << std::endl;
for(DirIter it = vd->_subdirs.begin(); it != vd->_subdirs.end(); ++it)
_DumpTreeRecursive(os, it->second, sub, vd);
for(FileIter it = vd->_files.begin(); it != vd->_files.end(); ++it)
{
VFSFile *vf = it->second;
// only if refcount and/or mount point differs
bool p = false;
if(vf->ref.count() != vd->ref.count())
{
doprint:
os << sub << "f|" << vf->name() << " [" << vf->getType() << ", ref " << vf->ref.count() << ", 0x" << vf << "]";
p = true;
}
if(strncmp(vd->fullname(), vf->fullname(), strlen(vd->fullname())))
{
if(!p)
goto doprint;
os << " <-- {" << vf->fullname() << "} ***********";
}
if(p)
os << std::endl;
}
}
void VFSHelper::debugDumpTree(std::ostream& os, VFSDir *start /* = NULL */)
{
_DumpTreeRecursive(os, start ? start : GetDirRoot(), "", NULL);
}
VFS_NAMESPACE_END

View file

@ -1,192 +0,0 @@
// VFSHelper.h - glues it all together and makes use simple
// For conditions of distribution and use, see copyright notice in VFS.h
#ifndef VFSHELPER_H
#define VFSHELPER_H
#include <set>
#include <vector>
#include <deque>
#include <list>
#include "VFSAtomic.h"
VFS_NAMESPACE_START
class VFSDir;
class VFSDirReal;
class VFSFile;
class VFSLoader;
/** VFSHelper - extensible class to simplify working with the VFS tree
* Contains a set of useful functions that should be useful for anyone.
* This class may be overridden to support adding any source in a comfortable way.
*
* Note: This class uses VFS_LAST_HELPER_CLASS, which should always store the last
* class derived from VFSHelper. This is supposed to make it easy to make extensions like this:
#include "VFSHelperExtra.h" // defines a VFSHelperExtra class that is somehow derived from VFSHelper
// and follows the same rules as explained below.
class VFSHelperArchive : public VFS_LAST_HELPER_CLASS
{
private:
typedef VFS_LAST_HELPER_CLASS super;
public:
// .... class members ....
};
#undef VFS_LAST_HELPER_CLASS
#define VFS_LAST_HELPER_CLASS VFSHelperArchive
* Used this way, only the order in which VFSHelper extension classes are included matters.
* No code changes are required to get a nice inheritance and priority chain working.
*
*/
#ifdef VFS_LAST_HELPER_CLASS
# error VFS_LAST_HELPER_CLASS defined before VFSHelper class decl, check your include order!
#endif
class VFSHelper
{
public:
VFSHelper();
virtual ~VFSHelper();
/** Creates the working tree. Required before any files or directories can be accessed.
Internally, it merges all individual VFS trees into one. If clear is true (default),
an existing merged tree is dropped, and old and previously added files and loaders removed.
(This is the recommended setting.) */
virtual void Prepare(bool clear = true);
/** Re-merges any files in the tree, and optionally reloads files on disk.
This is useful if files on disk were created or removed, and the tree needs to reflect these changes. */
virtual void Reload(bool fromDisk = false);
/** Reset an instance to its initial state */
virtual void Clear(void);
/** Load all files from working directory (into an internal tree) */
bool LoadFileSysRoot(void);
/** Mount a directory in the tree to a different location. Requires a previous call to Prepare().
This can be imagined like a symlink pointing to a different location.
Be careful not to create circles, this might technically work,
but confuses the reference counting, causing memory leaks. */
bool Mount(const char *src, const char *dest, bool overwrite = true);
/** Drops a directory from the tree. Internally, this calls Reload(false),
which is a heavy operation compared to Mount(). Be warned. */
bool Unmount(const char *src, const char *dest);
/** Merges a path into the tree. Requires a previous call to Prepare().
By default the directory is added into the root directory of the merged tree.
Pass NULL to add the directory to its original location,
or any other path to add it to that explicit location.
It is advised not to use this to re-add parts already in the tree; use Mount() instead.
Rule of thumb: If you called LoadFileSysRoot(), do not use this for subdirs. */
bool MountExternalPath(const char *path, const char *where = "");
/** Adds a VFSDir object into the merged tree. If subdir is NULL (the default),
add into the subdir stored in the VFSDir object. The tree will be extended if target dir does not exist.
If overwrite is true (the default), files in the tree will be replaced if already existing.
Requires a previous call to Prepare().
Like with Mount(); be careful not to create cycles. */
bool AddVFSDir(VFSDir *dir, const char *subdir = NULL, bool overwrite = true);
/** Add a loader that can look for files on demand.
It will be deleted if Prepare(true) is called.
It is possible (but not a good idea) to add a loader multiple times. */
inline void AddLoader(VFSLoader *ldr);
/** Get a file from the merged tree. Requires a previous call to Prepare().
Asks loaders if the file is not in the tree. If found by a loader, the file will be added to the tree.
The returned pointer is reference counted. In case the file pointer is stored elsewhere,
do ptr->ref++, and later ptr->ref--. This is to prevent the VFS tree from deleting the file when cleaning up.
Not necessary if the pointer is just retrieved and used, or temp. stored while the VFS tree is not modified. */
VFSFile *GetFile(const char *fn);
/** Get a directory from the merged tree. If create is true and the directory does not exist,
build the tree structure and return the newly created dir. NULL otherwise.
Requires a previous call to Prepare().
Reference counted, same as GetFile(), look there for more info. */
VFSDir *GetDir(const char* dn, bool create = false);
/** Returns the tree root, which is usually the working directory. */
VFSDir *GetDirRoot(void);
/** Remove a file or directory from the tree */
//bool Remove(VFSFile *vf);
//bool Remove(VFSDir *dir);
//bool Remove(const char *name); // TODO: CODE ME
/** This depends on the class type and stays constant. */
inline unsigned int FixedLoadersCount(void) const { return (unsigned int)fixedLdrs.size(); }
inline void lock() { _mtx.Lock(); }
inline void unlock() { _mtx.Unlock(); }
inline Mutex& mutex() const { return _mtx; }
// DEBUG STUFF
void debugDumpTree(std::ostream& os, VFSDir *start = NULL);
protected:
/** Drops the merged tree and additional mount points and dynamic loaders.
Overload to do additional cleanup if required. Invoked by Clear() and Prepare(true). */
virtual void _cleanup(void);
/** Add a fixed VFSLoader. Returns its array index in fixedLdrs. */
unsigned int _AddFixedLoader(VFSLoader *ldr = NULL);
struct VDirEntry
{
VDirEntry() : vdir(NULL), overwrite(false) {}
VDirEntry(VFSDir *v, std::string mp, bool ow) : vdir(v), mountPoint(mp), overwrite(ow) {}
VFSDir *vdir;
std::string mountPoint;
bool overwrite;
};
typedef std::list<VDirEntry> VFSMountList;
typedef std::vector<VFSLoader*> LoaderArray;
typedef std::deque<VFSLoader*> LoaderList;
typedef std::vector<VFSDir*> DirArray;
void _StoreMountPoint(const VDirEntry& ve);
bool _RemoveMountPoint(const VDirEntry& ve);
// the VFSDirs are merged in their declaration order.
// when merging, files already contained can be overwritten by files merged in later.
VFSDirReal *filesysRoot; // local files on disk (root dir)
// Additional tree stores, to be filled by subclasses if needed.
DirArray preRoot; // VFSDirs in here will be merged in, before the actual disk files.
// Means files on disk will overwrite existing entries.
DirArray postRoot; // Will be merged after the disk files, and overwrite prev. merged files.
// Both may contain NULLs.
// if files are not in the tree, maybe one of these is able to find it. May contain NULLs.
LoaderArray fixedLdrs; // defined by class type, stays constant during object lifetime
LoaderList dynLdrs; // dynamically added on demand, deleted on _cleanup()
VFSDir *merged; // contains the merged virtual/actual file system tree
mutable Mutex _mtx;
private:
unsigned int _ldrDiskId;
VFSMountList vlist; // all other dirs added later, together with path to mount to
};
#undef VFS_LAST_HELPER_CLASS
#define VFS_LAST_HELPER_CLASS VFSHelper
VFS_NAMESPACE_END
#endif

View file

@ -1,43 +0,0 @@
// VFSInternal.h - misc things that are not required to be visible outside of the library.
// For conditions of distribution and use, see copyright notice in VFS.h
// !! this file is supposed to be included ONLY from VFS*.cpp files.
#ifndef VFS_INTERNAL_H
#define VFS_INTERNAL_H
// checks to enforcecorrect including
#ifdef TTVFS_VFS_H
#error Oops, TTVFS_VFS_H is defined, someone messed up and included VFS.h wrongly.
#endif
#include "VFSDefines.h"
#if _MSC_VER
# define _CRT_SECURE_NO_WARNINGS
# define _CRT_SECURE_NO_DEPRECATE
# pragma warning(disable: 4355) // 'this' : used in base member initializer list
#endif
// this is for POSIX - define before including any stdio headers
#ifdef VFS_LARGEFILE_SUPPORT
# ifndef _MSC_VER
# define _FILE_OFFSET_BITS 64
# endif
#endif
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <string>
// this is for MSVC - re-define functions
#ifdef VFS_LARGEFILE_SUPPORT
# ifdef _MSC_VER
# define fseek _fseeki64
# define ftell _ftelli64
# endif
#endif
#endif

View file

@ -1,102 +0,0 @@
// VFSLoader.cpp - late loading of files not in the tree
// For conditions of distribution and use, see copyright notice in VFS.h
#include "VFSInternal.h"
#include "VFSTools.h"
#include "VFSFile.h"
#include "VFSLoader.h"
VFS_NAMESPACE_START
#if !defined(_WIN32) && defined(VFS_IGNORE_CASE)
#include <sys/dir.h>
// based on code in PhysicsFS: http://icculus.org/physfs/
static bool locateOneElement(char *buf)
{
char *ptr;
DIR *dirp;
ptr = strrchr(buf, '/'); // find entry at end of path.
if (ptr == NULL)
{
dirp = opendir(".");
ptr = buf;
}
else
{
*ptr = '\0';
dirp = opendir(buf);
*ptr = '/';
ptr++; // point past dirsep to entry itself.
}
struct dirent *dent;
while ((dent = readdir(dirp)) != NULL)
{
if (strcasecmp(dent->d_name, ptr) == 0)
{
strcpy(ptr, dent->d_name); // found a match. Overwrite with this case.
closedir(dirp);
return true;
}
}
// no match at all...
closedir(dirp);
return false;
}
static bool findFileHarder(char *fn)
{
char *ptr = fn;
bool found = true;
while ((ptr = strchr(ptr + 1, '/')) != 0)
{
*ptr = '\0';
found = locateOneElement(fn);
*ptr = '/'; // restore path separator
if (!found)
return false;
}
// check final element...
found = found && locateOneElement(fn);
printf("tt: Fixed case '%s' [%s]\n", fn, found ? "found" : "NOT FOUND"); // TEMP
return found;
}
#endif
VFSFile *VFSLoaderDisk::Load(const char *fn)
{
if(FileExists(fn))
return new VFSFileReal(fn); // must contain full file name
#if !defined(_WIN32) && defined(VFS_IGNORE_CASE)
size_t s = strlen(fn);
if(s < 511) // avoid using malloc() and alloca() for short strings
{
char t[512];
memcpy(&t[0], fn, s+1); // copy terminating '\0' as well
if(findFileHarder(&t[0])) // fixes the filename on the way
return new VFSFileReal(&t[0]);
}
else
{
char *t = (char*)malloc(s+1);
VFSFileReal *vf = NULL;
memcpy(t, fn, s+1);
if(findFileHarder(&t[0]))
vf = new VFSFileReal(&t[0]);
free(t);
return vf;
}
#endif
return NULL;
}
VFS_NAMESPACE_END

View file

@ -1,31 +0,0 @@
// VFSLoader.h - late loading of files not in the tree
// For conditions of distribution and use, see copyright notice in VFS.h
#ifndef VFSLOADER_H
#define VFSLOADER_H
#include "VFSDefines.h"
VFS_NAMESPACE_START
class VFSFile;
// VFSLoader - to be called if a file is not in the tree.
class VFSLoader
{
public:
virtual ~VFSLoader() {}
virtual VFSFile *Load(const char *fn) = 0;
};
class VFSLoaderDisk : public VFSLoader
{
public:
virtual ~VFSLoaderDisk() {}
virtual VFSFile *Load(const char *fn);
};
VFS_NAMESPACE_END
#endif

View file

@ -1,44 +0,0 @@
#ifndef SELFREFCOUNTER_H
#define SELFREFCOUNTER_H
#include "VFSDefines.h"
#include "VFSAtomic.h"
VFS_NAMESPACE_START
// self must point to the object that holds the counter.
template <class T, bool DELSELF = true> class SelfRefCounter
{
private:
T *self;
volatile int c;
SelfRefCounter(SelfRefCounter& r); // forbid copy constructor
inline unsigned int _deref(void)
{
unsigned int cc = (unsigned int)Atomic_Decr(c); // copy c, in case we get deleted
if(DELSELF && !cc)
{
delete self;
}
return cc;
}
public:
SelfRefCounter(T *p): self(p), c(1) {}
~SelfRefCounter() { /* DEBUG(ASSERT(c <= 1)); */ } // its ok if the last reference calls delete instead of _deref()
inline unsigned int count(void) { return c; }
// post-increment (dummy int)
inline unsigned int operator++(int) { unsigned int cc = c; Atomic_Incr(c); return cc; }
inline unsigned int operator--(int) { unsigned int cc = c; _deref(); return cc; }
// pre-increment
inline unsigned int operator++(void) { return (unsigned int)Atomic_Incr(c); }
inline unsigned int operator--(void) { return _deref(); }
};
VFS_NAMESPACE_END
#endif

View file

@ -1,427 +0,0 @@
// VFSTools.cpp - useful functions and misc stuff
// For conditions of distribution and use, see copyright notice in VFS.h
#include "VFSInternal.h"
#include <cstdlib>
#include <algorithm>
#include <cctype>
#include <stack>
#include "VFSTools.h"
#if _WIN32
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
#else
# include <sys/dir.h>
# include <sys/stat.h>
# include <sys/types.h>
# include <unistd.h>
#endif
VFS_NAMESPACE_START
std::string stringToLower(std::string s)
{
std::transform(s.begin(), s.end(), s.begin(), tolower);
return s;
}
std::string stringToUpper(std::string s)
{
std::transform(s.begin(), s.end(), s.begin(), toupper);
return s;
}
void makeLowercase(std::string& s)
{
std::transform(s.begin(), s.end(), s.begin(), tolower);
}
void makeUppercase(std::string& s)
{
std::transform(s.begin(), s.end(), s.begin(), toupper);
}
// returns list of *plain* file names in given directory,
// without paths, and without anything else
void GetFileList(const char *path, StringList& files)
{
#if !_WIN32
DIR * dirp;
struct dirent * dp;
dirp = opendir(path);
if(dirp)
{
while((dp=readdir(dirp)) != NULL)
{
if (dp->d_type != DT_DIR) // only add if it is not a directory
{
std::string s(dp->d_name);
files.push_back(s);
}
}
closedir(dirp);
}
# else
WIN32_FIND_DATA fil;
std::string search(path);
MakeSlashTerminated(search);
search += "*";
HANDLE hFil = FindFirstFile(search.c_str(),&fil);
if(hFil != INVALID_HANDLE_VALUE)
{
do
{
if(!(fil.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
std::string s(fil.cFileName);
files.push_back(s);
}
}
while(FindNextFile(hFil, &fil));
FindClose(hFil);
}
# endif
}
// returns a list of directory names in the given directory, *without* the source dir.
// if getting the dir list recursively, all paths are added, except *again* the top source dir beeing queried.
void GetDirList(const char *path, StringList &dirs, bool recursive /* = false */)
{
#if !_WIN32
DIR * dirp;
struct dirent * dp;
dirp = opendir(path);
if(dirp)
{
while((dp = readdir(dirp))) // assignment is intentional
{
if (dp->d_type == DT_DIR) // only add if it is a directory
{
if(strcmp(dp->d_name, ".") != 0 && strcmp(dp->d_name, "..") != 0)
{
dirs.push_back(dp->d_name);
if (recursive) // needing a better way to do that
{
std::deque<std::string> newdirs;
GetDirList(dp->d_name, newdirs, true);
std::string d(dp->d_name);
for(std::deque<std::string>::iterator it = newdirs.begin(); it != newdirs.end(); ++it)
dirs.push_back(d + *it);
}
}
}
}
closedir(dirp);
}
#else
std::string search(path);
MakeSlashTerminated(search);
search += "*";
WIN32_FIND_DATA fil;
HANDLE hFil = FindFirstFile(search.c_str(),&fil);
if(hFil != INVALID_HANDLE_VALUE)
{
do
{
if( fil.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
{
if (!strcmp(fil.cFileName, ".") || !strcmp(fil.cFileName, ".."))
continue;
std::string d(fil.cFileName);
dirs.push_back(d);
if (recursive) // need a better way to do that
{
StringList newdirs;
GetDirList(d.c_str(), newdirs, true);
for(std::deque<std::string>::iterator it = newdirs.begin(); it != newdirs.end(); ++it)
dirs.push_back(d + *it);
}
}
}
while(FindNextFile(hFil, &fil));
FindClose(hFil);
}
#endif
}
bool FileExists(const char *fn)
{
#ifdef _WIN32
FILE *fp = fopen(fn, "rb");
if(fp)
{
fclose(fp);
return true;
}
return false;
#else
return access(fn, F_OK) == 0;
#endif
}
// must return true if creating the directory was successful, or already exists
bool CreateDir(const char *dir)
{
if(IsDirectory(dir)) // do not try to create if it already exists
return true;
bool result;
# if _WIN32
result = !!::CreateDirectory(dir, NULL);
# else
result = !mkdir(dir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
#endif
return result;
}
bool CreateDirRec(const char *dir)
{
if(IsDirectory(dir))
return true;
bool result = true;
StringList li;
StrSplit(dir, "/\\", li, false);
std::string d;
d.reserve(strlen(dir));
bool last;
for(StringList::iterator it = li.begin(); it != li.end(); it++)
{
d += *it;
last = CreateDir(d.c_str());
result = last && result;
d += '/';
}
return result || last;
}
vfspos GetFileSize(const char* fn)
{
if(!fn || !*fn)
return 0;
FILE *fp = fopen(fn, "rb");
if(!fp)
return 0;
fseek(fp, 0, SEEK_END);
vfspos s = (vfspos)ftell(fp);
fclose(fp);
return s == npos ? 0 : s;
}
std::string FixSlashes(const std::string& s)
{
std::string r;
r.reserve(s.length() + 1);
char last = 0, cur;
for(size_t i = 0; i < s.length(); ++i)
{
cur = s[i];
if(cur == '\\')
cur = '/';
if(last == '/' && cur == '/')
continue;
r += cur;
last = cur;
}
return r;
}
std::string FixPath(const std::string& s)
{
const char *p = s.c_str();
while(p[0] == '.' && p[1] == '/')
p += 2;
return FixSlashes(p == s.c_str() ? s : p); // avoid hidden re-allocation when pointer was not moved
}
bool IsDirectory(const char *s)
{
#if _WIN32
DWORD dwFileAttr = GetFileAttributes(s);
if(dwFileAttr == INVALID_FILE_ATTRIBUTES)
return false;
return !!(dwFileAttr & FILE_ATTRIBUTE_DIRECTORY);
#else
if ( access( s, 0 ) == 0 )
{
struct stat status;
stat( s, &status );
return status.st_mode & S_IFDIR;
}
return false;
#endif
}
void MakeSlashTerminated(std::string& s)
{
if(s.length() && s[s.length() - 1] != '/')
s += '/';
}
// extracts the file name from a given path
const char *PathToFileName(const char *str)
{
const char *p = strrchr(str, '/');
return p ? p+1 : str;
}
std::string StripFileExtension(const std::string& s)
{
size_t pos = s.find_last_of('.');
size_t pos2 = s.find_last_of('/');
if(pos != std::string::npos && (pos2 < pos || pos2 == std::string::npos))
return s.substr(0, pos);
return s;
}
std::string StripLastPath(const std::string& s)
{
if(s[s.length() - 1] == '/')
return StripLastPath(s.substr(0, s.length() - 1));
size_t pos = s.find_last_of('/');
if(pos == std::string::npos)
return ""; // nothing remains
return s.substr(0, pos);
}
void GetFileListRecursive(std::string dir, StringList& files, bool withQueriedDir /* = false */)
{
std::stack<std::string> stk;
if(withQueriedDir)
{
stk.push(dir);
while(stk.size())
{
dir = stk.top();
stk.pop();
MakeSlashTerminated(dir);
StringList li;
GetFileList(dir.c_str(), li);
for(std::deque<std::string>::iterator it = li.begin(); it != li.end(); ++it)
files.push_back(dir + *it);
li.clear();
GetDirList(dir.c_str(), li, true);
for(std::deque<std::string>::iterator it = li.begin(); it != li.end(); ++it)
stk.push(dir + *it);
}
}
else
{
std::string topdir = dir;
MakeSlashTerminated(topdir);
stk.push("");
while(stk.size())
{
dir = stk.top();
stk.pop();
MakeSlashTerminated(dir);
StringList li;
dir = topdir + dir;
GetFileList(dir.c_str(), li);
for(std::deque<std::string>::iterator it = li.begin(); it != li.end(); ++it)
files.push_back(dir + *it);
li.clear();
GetDirList(dir.c_str(), li, true);
for(std::deque<std::string>::iterator it = li.begin(); it != li.end(); ++it)
stk.push(dir + *it);
}
}
}
// from http://board.byuu.org/viewtopic.php?f=10&t=1089&start=15
bool WildcardMatch(const char *str, const char *pattern)
{
const char *cp = 0, *mp = 0;
while(*str && *pattern != '*')
{
if(*pattern != *str && *pattern != '?')
return false;
pattern++, str++;
}
while(*str)
{
if(*pattern == '*')
{
if(!*++pattern)
return 1;
mp = pattern;
cp = str + 1;
}
else if(*pattern == *str || *pattern == '?')
{
++pattern;
++str;
}
else
{
pattern = mp;
str = cp++;
}
}
while(*pattern++ == '*');
return !*pattern;
}
// copy strings, mangling newlines to system standard
// windows has 13+10
// *nix has 10
// exotic systems may have 10+13
size_t strnNLcpy(char *dst, const char *src, unsigned int n /* = -1 */)
{
char *olddst = dst;
bool had10 = false, had13 = false;
--n; // reserve 1 for \0 at end
while(*src && n)
{
if((had13 && *src == 10) || (had10 && *src == 13))
{
++src; // last was already mangled
had13 = had10 = false; // processed one CRLF pair
continue;
}
had10 = *src == 10;
had13 = *src == 13;
if(had10 || had13)
{
*dst++ = '\n';
++src;
}
else
*dst++ = *src++;
--n;
}
*dst++ = 0;
return dst - olddst;
}
VFS_NAMESPACE_END

View file

@ -1,59 +0,0 @@
// VFSTools.h - useful functions and misc stuff
// For conditions of distribution and use, see copyright notice in VFS.h
#ifndef VFS_TOOLS_H
#define VFS_TOOLS_H
#include <deque>
#include <string>
#include "VFSDefines.h"
VFS_NAMESPACE_START
typedef std::deque<std::string> StringList;
std::string stringToUpper(const std::string& s);
std::string stringToLower(const std::string& s);
void makeUppercase(std::string& s);
void makeLowercase(std::string& s);
void GetFileList(const char *, StringList& files);
void GetDirList(const char *, StringList& dirs, bool recursive = false);
bool FileExists(const char *);
bool IsDirectory(const char *);
bool CreateDir(const char*);
bool CreateDirRec(const char*);
vfspos GetFileSize(const char*);
std::string FixSlashes(const std::string& s);
std::string FixPath(const std::string& s);
const char *PathToFileName(const char *str);
void MakeSlashTerminated(std::string& s);
std::string StripFileExtension(const std::string& s);
std::string StripLastPath(const std::string& s);
void GetFileListRecursive(std::string dir, StringList& files, bool withQueriedDir = false);
bool WildcardMatch(const char *str, const char *pattern);
size_t strnNLcpy(char *dst, const char *src, unsigned int n = -1);
template <class T> void StrSplit(const std::string &src, const std::string &sep, T& container, bool keepEmpty = false)
{
std::string s;
for (std::string::const_iterator i = src.begin(); i != src.end(); i++)
{
if (sep.find(*i) != std::string::npos)
{
if (keepEmpty || s.length())
container.push_back(s);
s = "";
}
else
{
s += *i;
}
}
if (keepEmpty || s.length())
container.push_back(s);
}
VFS_NAMESPACE_END
#endif