1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-16 18:49:58 +00:00

Added VFS+tests, make Ogre::Archive client implementation.

This commit is contained in:
Nicolay Korslund 2009-12-19 20:53:53 +01:00
parent 7139f5284d
commit bbb44e07bf
11 changed files with 457 additions and 2 deletions

View file

@ -564,7 +564,7 @@ WARN_LOGFILE =
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
INPUT = sound
INPUT = sound stream vfs
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is

View file

@ -1,5 +1,5 @@
// This file is shared between several test programs
#include "input.h"
#include "../input.h"
#include <assert.h>
#include <string.h>

View file

@ -0,0 +1,83 @@
#include "ogre_archive.h"
#include "../../stream/imp_client/ogre_datastream.h"
using namespace Mangle::VFS;
using namespace Mangle::Stream;
Ogre::DataStreamPtr MangleArchive::open(const Ogre::String& filename) const
{
return Ogre::DataStreamPtr(new MangleDataStream
(filename, vfs->open(filename), true));
}
static void fill(Ogre::FileInfoList &out, FileInfoList &in)
{
int size = in.size();
out.resize(size);
for(int i=0; i<size; i++)
{
out[i].filename = in[i].name;
out[i].basename = in[i].basename;
out[i].path = ""; // FIXME
out[i].uncompressedSize = in[i].size;
out[i].compressedSize = in[i].size;
}
}
static void fill(Ogre::StringVector &out, FileInfoList &in)
{
int size = in.size();
out.resize(size);
for(int i=0; i<size; i++)
out[i] = in[i].name;
}
Ogre::StringVectorPtr MangleArchive::list(bool recursive, bool dirs)
{
FileInfoList lst = vfs->list("", recursive, dirs);
Ogre::StringVector *res = new Ogre::StringVector;
fill(*res, lst);
return Ogre::StringVectorPtr(res);
}
Ogre::FileInfoListPtr MangleArchive::listFileInfo(bool recursive, bool dirs)
{
FileInfoList lst = vfs->list("", recursive, dirs);
Ogre::FileInfoList *res = new Ogre::FileInfoList;
fill(*res, lst);
return Ogre::FileInfoListPtr(res);
}
// Find functions will only work if vfs->hasFind is set.
Ogre::StringVectorPtr MangleArchive::find(const Ogre::String& pattern,
bool recursive,
bool dirs)
{
assert(vfs->hasFind);
FileInfoList lst = vfs->find(pattern, recursive, dirs);
Ogre::StringVector *res = new Ogre::StringVector;
fill(*res, lst);
return Ogre::StringVectorPtr(res);
}
Ogre::FileInfoListPtr MangleArchive::findFileInfo(const Ogre::String& pattern,
bool recursive,
bool dirs)
{
assert(vfs->hasFind);
FileInfoList lst = vfs->find(pattern, recursive, dirs);
Ogre::FileInfoList *res = new Ogre::FileInfoList;
fill(*res, lst);
return Ogre::FileInfoListPtr(res);
}

View file

@ -0,0 +1,53 @@
#ifndef MANGLE_VFS_OGRECLIENT_H
#define MANGLE_VFS_OGRECLIENT_H
#include <OgreArchive.h>
#include <assert.h>
#include "wrapper.h"
namespace Mangle {
namespace VFS {
/** An OGRE Archive implementation that wraps a Mangle::VFS
filesystem.
This has been built and tested against OGRE 1.6.2. You might have
to make your own modifications if you're working with newer (or
older) versions.
*/
class MangleArchive : public Ogre::Archive, _Wrapper
{
public:
/// Constructor without name
MangleArchive(VFS *vfs, const std::string &name,
const std::string &archType = "Mangle",
bool autoDel=false)
: _Wrapper(vfs, autoDel), Ogre::Archive(name, archType) {}
bool isCaseSensitive() const { return vfs->isCaseSensitive; }
// These do nothing. You have to load / unload the archive manually.
void load() {}
void unload() {}
bool exists(const Ogre::String& filename)
{ return vfs->isFile(filename); }
time_t getModifiedTime(const Ogre::String& filename)
{ return vfs->stat(filename).time; }
Ogre::DataStreamPtr open(const Ogre::String& filename) const;
Ogre::StringVectorPtr list(bool recursive = true, bool dirs = false);
Ogre::FileInfoListPtr listFileInfo(bool recursive = true, bool dirs = false);
// Find functions will only work if vfs->hasFind is set.
Ogre::StringVectorPtr find(const Ogre::String& pattern, bool recursive = true,
bool dirs = false);
Ogre::FileInfoListPtr findFileInfo(const Ogre::String& pattern,
bool recursive = true,
bool dirs = false);
};
}} // namespaces
#endif

30
vfs/imp_client/wrapper.h Normal file
View file

@ -0,0 +1,30 @@
#ifndef MANGLE_VFS_WRAPPER_H
#define MANGLE_VFS_WRAPPER_H
#include "../vfs.h"
#include <assert.h>
namespace Mangle {
namespace VFS {
/** A generic wrapper class for a VFS::VFS object.
This is used by other implementations.
*/
class _Wrapper
{
private:
bool autoDel;
protected:
VFS *vfs;
public:
_Wrapper(VFS *_vfs, bool _autoDel = false)
: vfs(_vfs), autoDel(_autoDel) { assert(vfs != NULL); }
virtual ~_Wrapper() { if(autoDel) delete vfs; }
};
}} // namespaces
#endif

1
vfs/tests/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
*_test

15
vfs/tests/Makefile Normal file
View file

@ -0,0 +1,15 @@
GCC=g++ -I../ -I../imp_client/
all: dummy_test ogre_client_test
I_OGRE=$(shell pkg-config --cflags OGRE)
L_OGRE=$(shell pkg-config --libs OGRE)
ogre_client_test: ogre_client_test.cpp dummy_vfs.cpp ../vfs.h ../imp_client/wrapper.h ../imp_client/ogre_archive.h ../imp_client/ogre_archive.cpp
$(GCC) $< ../imp_client/ogre_archive.cpp -o $@ $(I_OGRE) $(L_OGRE)
dummy_test: dummy_test.cpp dummy_vfs.cpp ../vfs.h
$(GCC) $< -o $@
clean:
rm *_test

40
vfs/tests/dummy_test.cpp Normal file
View file

@ -0,0 +1,40 @@
#include "dummy_vfs.cpp"
#include <iostream>
#include <string.h>
using namespace std;
void print(FileInfo inf)
{
cout << "name: " << inf.name << endl;
cout << "basename: " << inf.basename << endl;
cout << "isDir: " << inf.isDir << endl;
cout << "size: " << inf.size << endl;
cout << "time: " << inf.time << endl;
}
void print(FileInfoList lst)
{
for(int i=0; i<lst.size(); i++)
print(lst[i]);
}
int main()
{
DummyVFS vfs;
cout << "Listing all files:\n";
print(vfs.list());
cout << "\nStat for single files:\n";
print(vfs.stat("file1"));
cout << endl;
print(vfs.stat("dir/file2"));
cout << endl;
print(vfs.stat("dir"));
InputStream *inp = vfs.open("file1");
cout << "filesize: " << inp->size() << endl;
return 0;
}

115
vfs/tests/dummy_vfs.cpp Normal file
View file

@ -0,0 +1,115 @@
// This file is shared between several test programs
#include "vfs.h"
#include <assert.h>
#include <string.h>
#include "../../stream/tests/dummy_input.cpp"
using namespace Mangle::VFS;
class DummyVFS : public VFS
{
public:
DummyVFS()
{
hasFind = false;
isCaseSensitive = true;
}
// We only support opening 'file1' at the moment.
Mangle::Stream::InputStream *open(const std::string &name)
{
assert(name == "file1");
return new DummyInput();
}
bool isFile(const std::string &name) const
{
return (name == "file1" ||
name == "dir/file2");
}
bool isDir(const std::string &name) const
{
return name == "dir";
}
/// Get info about a single file
FileInfo stat(const std::string &name) const
{
FileInfo fi;
fi.name = name;
fi.time = 0;
if(isFile(name))
{
if(name == "dir/file2")
{
fi.basename = "file2";
fi.size = 2;
}
else
{
fi.basename = "file1";
fi.size = 1;
}
fi.isDir = false;
}
else if(isDir(name))
{
fi.basename = "dir";
fi.isDir = true;
fi.size = 0;
}
else assert(0);
return fi;
}
/// List all entries in a given directory. A blank dir should be
/// interpreted as a the root/current directory of the archive. If
/// dirs is true, list directories instead of files.
virtual FileInfoList list(const std::string& dir = "",
bool recurse=true,
bool dirs=false) const
{
assert(dir == "");
FileInfoList fl;
FileInfo fi;
if(!dirs)
{
fi.name = "file1";
fi.basename = "file1";
fi.isDir = false;
fi.size = 1;
fi.time = 0;
fl.push_back(fi);
if(recurse)
{
fi.name = "dir/file2";
fi.basename = "file2";
fi.size = 2;
fl.push_back(fi);
}
}
else
{
fi.name = "dir";
fi.basename = "dir";
fi.isDir = true;
fi.size = 0;
fi.time = 0;
fl.push_back(fi);
}
return fl;
}
FileInfoList find(const std::string& pattern,
bool recursive=true,
bool dirs=false) const
{ assert(0); return FileInfoList(); }
};

View file

@ -0,0 +1,39 @@
#include "dummy_vfs.cpp"
#include "ogre_archive.h"
#include <iostream>
using namespace Ogre;
using namespace std;
void print(StringVectorPtr lst)
{
int s = lst->size();
for(int i=0; i<s; i++)
{
cout << " " << (*lst)[i] << endl;
}
}
int main()
{
VFS *vfs = new DummyVFS();
MangleArchive arc(vfs, "dummy");
cout << "Case: " << arc.isCaseSensitive() << endl;
cout << "Name: " << arc.getName() << endl;
cout << "Type: " << arc.getType() << endl;
cout << "All files:\n";
print(arc.list());
cout << "Non-recursive:\n";
print(arc.list(false, false));
cout << "Dirs:\n";
print(arc.list(false, true));
DataStreamPtr file = arc.open("file1");
cout << "filesize: " << file->size() << endl;
cout << "contents: " << file->getAsString() << endl;
return 0;
}

79
vfs/vfs.h Normal file
View file

@ -0,0 +1,79 @@
#ifndef MANGLE_VFS_H
#define MANGLE_VFS_H
#include "../stream/input.h"
#include <string>
#include <vector>
namespace Mangle {
namespace VFS {
/// Generic file info structure
struct FileInfo
{
/// Full name, including path
std::string name;
/// Base name, not including path
std::string basename;
/// Is this a directory?
bool isDir;
/// File size
size_t size;
/// Last modification date
time_t time;
};
typedef std::vector<FileInfo> FileInfoList;
/** An interface to any file system or other provider of named data
streams
*/
class VFS
{
public:
// Feature options. These should be set in the constructor.
/// If true, the find*() functions work
bool hasFind;
/// If true, the file system is case sensitive
bool isCaseSensitive;
/// Virtual destructor
virtual ~VFS() {}
/// Open a new data stream. Deleting the object should be enough to
/// close it.
virtual Stream::InputStream *open(const std::string &name) = 0;
/// Check for the existence of a file
virtual bool isFile(const std::string &name) const = 0;
/// Check for the existence of a directory
virtual bool isDir(const std::string &name) const = 0;
/// Get info about a single file
virtual FileInfo stat(const std::string &name) const = 0;
/// List all entries in a given directory. A blank dir should be
/// interpreted as a the root/current directory of the archive. If
/// dirs is true, list directories instead of files.
virtual FileInfoList list(const std::string& dir = "",
bool recurse=true,
bool dirs=false) const = 0;
/// Find files after a given pattern. Wildcards (*) are
/// supported. Only valid if 'hasFind' is true. Don't implement your
/// own pattern matching here if the backend doesn't support it
/// natively; use a filter instead.
virtual FileInfoList find(const std::string& pattern,
bool recursive=true,
bool dirs=false) const = 0;
};
}} // namespaces
#endif