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:
parent
7139f5284d
commit
bbb44e07bf
11 changed files with 457 additions and 2 deletions
2
Doxyfile
2
Doxyfile
|
@ -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
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// This file is shared between several test programs
|
||||
#include "input.h"
|
||||
#include "../input.h"
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
|
|
83
vfs/imp_client/ogre_archive.cpp
Normal file
83
vfs/imp_client/ogre_archive.cpp
Normal 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);
|
||||
}
|
53
vfs/imp_client/ogre_archive.h
Normal file
53
vfs/imp_client/ogre_archive.h
Normal 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
30
vfs/imp_client/wrapper.h
Normal 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
1
vfs/tests/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
*_test
|
15
vfs/tests/Makefile
Normal file
15
vfs/tests/Makefile
Normal 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
40
vfs/tests/dummy_test.cpp
Normal 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
115
vfs/tests/dummy_vfs.cpp
Normal 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(); }
|
||||
};
|
39
vfs/tests/ogre_client_test.cpp
Normal file
39
vfs/tests/ogre_client_test.cpp
Normal 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
79
vfs/vfs.h
Normal 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
|
Loading…
Reference in a new issue