mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-19 20:53:50 +00:00
Merge remote branch 'zini/master' into nif-cleanup
Conflicts: components/bsa/bsa_archive.cpp
This commit is contained in:
commit
b4c8375f3c
68 changed files with 279 additions and 2943 deletions
|
@ -101,9 +101,8 @@ ENDIF()
|
||||||
|
|
||||||
set(LIBDIR ${CMAKE_SOURCE_DIR}/libs)
|
set(LIBDIR ${CMAKE_SOURCE_DIR}/libs)
|
||||||
|
|
||||||
set(MANGLE_VFS ${LIBDIR}/mangle/vfs/servers/ogre_vfs.cpp)
|
|
||||||
set(MANGLE_INPUT ${LIBDIR}/mangle/input/servers/ois_driver.cpp)
|
set(MANGLE_INPUT ${LIBDIR}/mangle/input/servers/ois_driver.cpp)
|
||||||
set(MANGLE_ALL ${MANGLE_VFS} ${MANGLE_INPUT})
|
set(MANGLE_ALL ${MANGLE_INPUT})
|
||||||
source_group(libs\\mangle FILES ${MANGLE_ALL})
|
source_group(libs\\mangle FILES ${MANGLE_ALL})
|
||||||
|
|
||||||
set(OENGINE_OGRE
|
set(OENGINE_OGRE
|
||||||
|
|
|
@ -79,7 +79,6 @@ ENDIF(WIN32)
|
||||||
ENDIF(OGRE_STATIC)
|
ENDIF(OGRE_STATIC)
|
||||||
add_executable(openmw
|
add_executable(openmw
|
||||||
${OPENMW_LIBS} ${OPENMW_LIBS_HEADER}
|
${OPENMW_LIBS} ${OPENMW_LIBS_HEADER}
|
||||||
${COMPONENT_FILES}
|
|
||||||
${OPENMW_FILES}
|
${OPENMW_FILES}
|
||||||
${GAME} ${GAME_HEADER}
|
${GAME} ${GAME_HEADER}
|
||||||
${APPLE_BUNDLE_RESOURCES}
|
${APPLE_BUNDLE_RESOURCES}
|
||||||
|
|
|
@ -28,13 +28,11 @@
|
||||||
#include <OgreArchiveFactory.h>
|
#include <OgreArchiveFactory.h>
|
||||||
#include <OgreArchiveManager.h>
|
#include <OgreArchiveManager.h>
|
||||||
#include "bsa_file.hpp"
|
#include "bsa_file.hpp"
|
||||||
#include <libs/mangle/stream/clients/ogre_datastream.hpp>
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
using namespace Ogre;
|
using namespace Ogre;
|
||||||
using namespace Mangle::Stream;
|
|
||||||
using namespace Bsa;
|
using namespace Bsa;
|
||||||
|
|
||||||
struct ciLessBoost : std::binary_function<std::string, std::string, bool>
|
struct ciLessBoost : std::binary_function<std::string, std::string, bool>
|
||||||
|
@ -213,10 +211,7 @@ public:
|
||||||
BSAFile *narc = const_cast<BSAFile*>(&arc);
|
BSAFile *narc = const_cast<BSAFile*>(&arc);
|
||||||
|
|
||||||
// Open the file
|
// Open the file
|
||||||
StreamPtr strm = narc->getFile(filename.c_str());
|
return narc->getFile(filename.c_str());
|
||||||
|
|
||||||
// Wrap it into an Ogre::DataStream.
|
|
||||||
return DataStreamPtr(new Mangle2OgreStream(strm));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool exists(const String& filename) {
|
bool exists(const String& filename) {
|
||||||
|
|
|
@ -23,171 +23,235 @@
|
||||||
|
|
||||||
#include "bsa_file.hpp"
|
#include "bsa_file.hpp"
|
||||||
|
|
||||||
#include <libs/mangle/stream/servers/file_stream.hpp>
|
|
||||||
#include <libs/mangle/stream/filters/slice_stream.hpp>
|
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <OgreDataStream.h>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace Mangle::Stream;
|
|
||||||
using namespace Bsa;
|
using namespace Bsa;
|
||||||
|
|
||||||
|
class ConstrainedDataStream : public Ogre::DataStream {
|
||||||
|
std::ifstream mStream;
|
||||||
|
const size_t mStart;
|
||||||
|
size_t mPos;
|
||||||
|
bool mIsEOF;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ConstrainedDataStream(const Ogre::String &fname, size_t start, size_t length)
|
||||||
|
: mStream(fname.c_str(), std::ios_base::binary), mStart(start), mPos(0), mIsEOF(false)
|
||||||
|
{
|
||||||
|
mSize = length;
|
||||||
|
if(!mStream.seekg(mStart, std::ios_base::beg))
|
||||||
|
throw std::runtime_error("Error seeking to start of BSA entry");
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstrainedDataStream(const Ogre::String &name, const Ogre::String &fname,
|
||||||
|
size_t start, size_t length)
|
||||||
|
: Ogre::DataStream(name), mStream(fname.c_str(), std::ios_base::binary),
|
||||||
|
mStart(start), mPos(0), mIsEOF(false)
|
||||||
|
{
|
||||||
|
mSize = length;
|
||||||
|
if(!mStream.seekg(mStart, std::ios_base::beg))
|
||||||
|
throw std::runtime_error("Error seeking to start of BSA entry");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual size_t read(void *buf, size_t count)
|
||||||
|
{
|
||||||
|
mStream.clear();
|
||||||
|
|
||||||
|
if(count > mSize-mPos)
|
||||||
|
{
|
||||||
|
count = mSize-mPos;
|
||||||
|
mIsEOF = true;
|
||||||
|
}
|
||||||
|
mStream.read(reinterpret_cast<char*>(buf), count);
|
||||||
|
|
||||||
|
count = mStream.gcount();
|
||||||
|
mPos += count;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void skip(long count)
|
||||||
|
{
|
||||||
|
if((count >= 0 && (size_t)count <= mSize-mPos) ||
|
||||||
|
(count < 0 && (size_t)-count <= mPos))
|
||||||
|
{
|
||||||
|
mStream.clear();
|
||||||
|
if(mStream.seekg(count, std::ios_base::cur))
|
||||||
|
{
|
||||||
|
mPos += count;
|
||||||
|
mIsEOF = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void seek(size_t pos)
|
||||||
|
{
|
||||||
|
if(pos < mSize)
|
||||||
|
{
|
||||||
|
mStream.clear();
|
||||||
|
if(mStream.seekg(pos+mStart, std::ios_base::beg))
|
||||||
|
{
|
||||||
|
mPos = pos;
|
||||||
|
mIsEOF = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual size_t tell() const
|
||||||
|
{ return mPos; }
|
||||||
|
|
||||||
|
virtual bool eof() const
|
||||||
|
{ return mIsEOF; }
|
||||||
|
|
||||||
|
virtual void close()
|
||||||
|
{ mStream.close(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/// Error handling
|
/// Error handling
|
||||||
void BSAFile::fail(const string &msg)
|
void BSAFile::fail(const string &msg)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("BSA Error: " + msg + "\nArchive: " + filename);
|
throw std::runtime_error("BSA Error: " + msg + "\nArchive: " + filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read header information from the input source
|
/// Read header information from the input source
|
||||||
void BSAFile::readHeader()
|
void BSAFile::readHeader()
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* The layout of a BSA archive is as follows:
|
* The layout of a BSA archive is as follows:
|
||||||
*
|
*
|
||||||
* - 12 bytes header, contains 3 ints:
|
* - 12 bytes header, contains 3 ints:
|
||||||
* id number - equal to 0x100
|
* id number - equal to 0x100
|
||||||
* dirsize - size of the directory block (see below)
|
* dirsize - size of the directory block (see below)
|
||||||
* numfiles - number of files
|
* numfiles - number of files
|
||||||
*
|
*
|
||||||
* ---------- start of directory block -----------
|
* ---------- start of directory block -----------
|
||||||
*
|
*
|
||||||
* - 8 bytes*numfiles, each record contains:
|
* - 8 bytes*numfiles, each record contains:
|
||||||
* fileSize
|
* fileSize
|
||||||
* offset into data buffer (see below)
|
* offset into data buffer (see below)
|
||||||
*
|
*
|
||||||
* - 4 bytes*numfiles, each record is an offset into the following name buffer
|
* - 4 bytes*numfiles, each record is an offset into the following name buffer
|
||||||
*
|
*
|
||||||
* - name buffer, indexed by the previous table, each string is
|
* - name buffer, indexed by the previous table, each string is
|
||||||
* null-terminated. Size is (dirsize - 12*numfiles).
|
* null-terminated. Size is (dirsize - 12*numfiles).
|
||||||
*
|
*
|
||||||
* ---------- end of directory block -------------
|
* ---------- end of directory block -------------
|
||||||
*
|
*
|
||||||
* - 8*filenum - hash table block, we currently ignore this
|
* - 8*filenum - hash table block, we currently ignore this
|
||||||
*
|
*
|
||||||
* ----------- start of data buffer --------------
|
* ----------- start of data buffer --------------
|
||||||
*
|
*
|
||||||
* - The rest of the archive is file data, indexed by the
|
* - The rest of the archive is file data, indexed by the
|
||||||
* offsets in the directory block. The offsets start at 0 at
|
* offsets in the directory block. The offsets start at 0 at
|
||||||
* the beginning of this buffer.
|
* the beginning of this buffer.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
assert(!isLoaded);
|
assert(!isLoaded);
|
||||||
assert(input);
|
|
||||||
assert(input->hasSize);
|
|
||||||
assert(input->hasPosition);
|
|
||||||
assert(input->isSeekable);
|
|
||||||
|
|
||||||
// Total archive size
|
std::ifstream input(filename.c_str(), std::ios_base::binary);
|
||||||
size_t fsize = input->size();
|
|
||||||
|
|
||||||
if( fsize < 12 )
|
// Total archive size
|
||||||
fail("File too small to be a valid BSA archive");
|
size_t fsize = 0;
|
||||||
|
if(input.seekg(0, std::ios_base::end))
|
||||||
// Get essential header numbers
|
|
||||||
size_t dirsize, filenum;
|
|
||||||
|
|
||||||
{
|
|
||||||
// First 12 bytes
|
|
||||||
uint32_t head[3];
|
|
||||||
|
|
||||||
input->read(head, 12);
|
|
||||||
|
|
||||||
if(head[0] != 0x100)
|
|
||||||
fail("Unrecognized BSA header");
|
|
||||||
|
|
||||||
// Total number of bytes used in size/offset-table + filename
|
|
||||||
// sections.
|
|
||||||
dirsize = head[1];
|
|
||||||
|
|
||||||
// Number of files
|
|
||||||
filenum = head[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Each file must take up at least 21 bytes of data in the bsa. So
|
|
||||||
// if files*21 overflows the file size then we are guaranteed that
|
|
||||||
// the archive is corrupt.
|
|
||||||
if( (filenum*21 > fsize -12) ||
|
|
||||||
(dirsize+8*filenum > fsize -12) )
|
|
||||||
fail("Directory information larger than entire archive");
|
|
||||||
|
|
||||||
// Read the offset info into a temporary buffer
|
|
||||||
vector<uint32_t> offsets(3*filenum);
|
|
||||||
input->read(&offsets[0], 12*filenum);
|
|
||||||
|
|
||||||
// Read the string table
|
|
||||||
stringBuf.resize(dirsize-12*filenum);
|
|
||||||
input->read(&stringBuf[0], stringBuf.size());
|
|
||||||
|
|
||||||
// Check our position
|
|
||||||
assert(input->tell() == 12+dirsize);
|
|
||||||
|
|
||||||
// Calculate the offset of the data buffer. All file offsets are
|
|
||||||
// relative to this. 12 header bytes + directory + hash table
|
|
||||||
// (skipped)
|
|
||||||
size_t fileDataOffset = 12 + dirsize + 8*filenum;
|
|
||||||
|
|
||||||
// Set up the the FileStruct table
|
|
||||||
files.resize(filenum);
|
|
||||||
for(size_t i=0;i<filenum;i++)
|
|
||||||
{
|
{
|
||||||
FileStruct &fs = files[i];
|
fsize = input.tellg();
|
||||||
fs.fileSize = offsets[i*2];
|
input.seekg(0);
|
||||||
fs.offset = offsets[i*2+1] + fileDataOffset;
|
|
||||||
fs.name = &stringBuf[offsets[2*filenum+i]];
|
|
||||||
|
|
||||||
if(fs.offset + fs.fileSize > fsize)
|
|
||||||
fail("Archive contains offsets outside itself");
|
|
||||||
|
|
||||||
// Add the file name to the lookup
|
|
||||||
lookup[fs.name] = i;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isLoaded = true;
|
if(fsize < 12)
|
||||||
|
fail("File too small to be a valid BSA archive");
|
||||||
|
|
||||||
|
// Get essential header numbers
|
||||||
|
size_t dirsize, filenum;
|
||||||
|
{
|
||||||
|
// First 12 bytes
|
||||||
|
uint32_t head[3];
|
||||||
|
|
||||||
|
input.read(reinterpret_cast<char*>(head), 12);
|
||||||
|
|
||||||
|
if(head[0] != 0x100)
|
||||||
|
fail("Unrecognized BSA header");
|
||||||
|
|
||||||
|
// Total number of bytes used in size/offset-table + filename
|
||||||
|
// sections.
|
||||||
|
dirsize = head[1];
|
||||||
|
|
||||||
|
// Number of files
|
||||||
|
filenum = head[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Each file must take up at least 21 bytes of data in the bsa. So
|
||||||
|
// if files*21 overflows the file size then we are guaranteed that
|
||||||
|
// the archive is corrupt.
|
||||||
|
if((filenum*21 > fsize -12) || (dirsize+8*filenum > fsize -12) )
|
||||||
|
fail("Directory information larger than entire archive");
|
||||||
|
|
||||||
|
// Read the offset info into a temporary buffer
|
||||||
|
vector<uint32_t> offsets(3*filenum);
|
||||||
|
input.read(reinterpret_cast<char*>(&offsets[0]), 12*filenum);
|
||||||
|
|
||||||
|
// Read the string table
|
||||||
|
stringBuf.resize(dirsize-12*filenum);
|
||||||
|
input.read(&stringBuf[0], stringBuf.size());
|
||||||
|
|
||||||
|
// Check our position
|
||||||
|
assert(input.tellg() == static_cast<int> (12+dirsize));
|
||||||
|
|
||||||
|
// Calculate the offset of the data buffer. All file offsets are
|
||||||
|
// relative to this. 12 header bytes + directory + hash table
|
||||||
|
// (skipped)
|
||||||
|
size_t fileDataOffset = 12 + dirsize + 8*filenum;
|
||||||
|
|
||||||
|
// Set up the the FileStruct table
|
||||||
|
files.resize(filenum);
|
||||||
|
for(size_t i=0;i<filenum;i++)
|
||||||
|
{
|
||||||
|
FileStruct &fs = files[i];
|
||||||
|
fs.fileSize = offsets[i*2];
|
||||||
|
fs.offset = offsets[i*2+1] + fileDataOffset;
|
||||||
|
fs.name = &stringBuf[offsets[2*filenum+i]];
|
||||||
|
|
||||||
|
if(fs.offset + fs.fileSize > fsize)
|
||||||
|
fail("Archive contains offsets outside itself");
|
||||||
|
|
||||||
|
// Add the file name to the lookup
|
||||||
|
lookup[fs.name] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
isLoaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the index of a given file name, or -1 if not found
|
/// Get the index of a given file name, or -1 if not found
|
||||||
int BSAFile::getIndex(const char *str) const
|
int BSAFile::getIndex(const char *str) const
|
||||||
{
|
{
|
||||||
Lookup::const_iterator it;
|
Lookup::const_iterator it = lookup.find(str);
|
||||||
it = lookup.find(str);
|
if(it == lookup.end())
|
||||||
|
return -1;
|
||||||
|
|
||||||
if(it == lookup.end()) return -1;
|
int res = it->second;
|
||||||
else
|
assert(res >= 0 && (size_t)res < files.size());
|
||||||
{
|
return res;
|
||||||
int res = it->second;
|
|
||||||
assert(res >= 0 && res < static_cast<int> (files.size()));
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Open an archive file.
|
/// Open an archive file.
|
||||||
void BSAFile::open(const string &file)
|
void BSAFile::open(const string &file)
|
||||||
{
|
{
|
||||||
filename = file;
|
filename = file;
|
||||||
input = StreamPtr(new FileStream(file));
|
readHeader();
|
||||||
readHeader();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Open an archive from a generic stream. The 'name' parameter is
|
Ogre::DataStreamPtr BSAFile::getFile(const char *file)
|
||||||
used for error messages.
|
|
||||||
*/
|
|
||||||
void BSAFile::open(StreamPtr inp, const string &name)
|
|
||||||
{
|
{
|
||||||
filename = name;
|
assert(file);
|
||||||
input = inp;
|
int i = getIndex(file);
|
||||||
readHeader();
|
if(i == -1)
|
||||||
}
|
fail("File not found: " + string(file));
|
||||||
|
|
||||||
StreamPtr BSAFile::getFile(const char *file)
|
const FileStruct &fs = files[i];
|
||||||
{
|
return Ogre::DataStreamPtr(new ConstrainedDataStream(filename, fs.offset, fs.fileSize));
|
||||||
assert(file);
|
|
||||||
int i = getIndex(file);
|
|
||||||
if(i == -1)
|
|
||||||
fail("File not found: " + string(file));
|
|
||||||
|
|
||||||
FileStruct &fs = files[i];
|
|
||||||
|
|
||||||
return StreamPtr(new SliceStream(input, fs.offset, fs.fileSize));
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,13 +24,15 @@
|
||||||
#ifndef BSA_BSA_FILE_H
|
#ifndef BSA_BSA_FILE_H
|
||||||
#define BSA_BSA_FILE_H
|
#define BSA_BSA_FILE_H
|
||||||
|
|
||||||
#include <libs/mangle/stream/stream.hpp>
|
|
||||||
#include <libs/platform/stdint.h>
|
#include <libs/platform/stdint.h>
|
||||||
#include <libs/platform/strings.h>
|
#include <libs/platform/strings.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
#include <OgreDataStream.h>
|
||||||
|
|
||||||
|
|
||||||
namespace Bsa
|
namespace Bsa
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -39,98 +41,85 @@ namespace Bsa
|
||||||
*/
|
*/
|
||||||
class BSAFile
|
class BSAFile
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
/// Represents one file entry in the archive
|
||||||
|
struct FileStruct
|
||||||
|
{
|
||||||
|
// File size and offset in file. We store the offset from the
|
||||||
|
// beginning of the file, not the offset into the data buffer
|
||||||
|
// (which is what is stored in the archive.)
|
||||||
|
uint32_t fileSize, offset;
|
||||||
|
|
||||||
/// Represents one file entry in the archive
|
// Zero-terminated file name
|
||||||
struct FileStruct
|
const char *name;
|
||||||
{
|
};
|
||||||
// File size and offset in file. We store the offset from the
|
typedef std::vector<FileStruct> FileList;
|
||||||
// beginning of the file, not the offset into the data buffer
|
|
||||||
// (which is what is stored in the archive.)
|
|
||||||
uint32_t fileSize, offset;
|
|
||||||
|
|
||||||
// Zero-terminated file name
|
private:
|
||||||
char* name;
|
/// Table of files in this archive
|
||||||
};
|
FileList files;
|
||||||
|
|
||||||
typedef std::vector<FileStruct> FileList;
|
/// Filename string buffer
|
||||||
|
std::vector<char> stringBuf;
|
||||||
|
|
||||||
private:
|
/// True when an archive has been loaded
|
||||||
|
bool isLoaded;
|
||||||
|
|
||||||
/// The archive source
|
/// Used for error messages
|
||||||
Mangle::Stream::StreamPtr input;
|
std::string filename;
|
||||||
|
|
||||||
/// Table of files in this archive
|
/// Case insensitive string comparison
|
||||||
FileList files;
|
struct iltstr
|
||||||
|
{
|
||||||
|
bool operator()(const char *s1, const char *s2) const
|
||||||
|
{ return strcasecmp(s1,s2) < 0; }
|
||||||
|
};
|
||||||
|
|
||||||
/// Filename string buffer
|
/** A map used for fast file name lookup. The value is the index into
|
||||||
std::vector<char> stringBuf;
|
the files[] vector above. The iltstr ensures that file name
|
||||||
|
checks are case insensitive.
|
||||||
|
*/
|
||||||
|
typedef std::map<const char*, int, iltstr> Lookup;
|
||||||
|
Lookup lookup;
|
||||||
|
|
||||||
/// True when an archive has been loaded
|
/// Error handling
|
||||||
bool isLoaded;
|
void fail(const std::string &msg);
|
||||||
|
|
||||||
/// Used for error messages
|
/// Read header information from the input source
|
||||||
std::string filename;
|
void readHeader();
|
||||||
|
|
||||||
/// Case insensitive string comparison
|
/// Get the index of a given file name, or -1 if not found
|
||||||
struct iltstr
|
int getIndex(const char *str) const;
|
||||||
{
|
|
||||||
bool operator()(const char *s1, const char *s2) const
|
|
||||||
{ return strcasecmp(s1,s2) < 0; }
|
|
||||||
};
|
|
||||||
|
|
||||||
/** A map used for fast file name lookup. The value is the index into
|
public:
|
||||||
the files[] vector above. The iltstr ensures that file name
|
/* -----------------------------------
|
||||||
checks are case insensitive.
|
* BSA management methods
|
||||||
*/
|
* -----------------------------------
|
||||||
typedef std::map<const char*, int, iltstr> Lookup;
|
*/
|
||||||
Lookup lookup;
|
|
||||||
|
|
||||||
/// Error handling
|
BSAFile()
|
||||||
void fail(const std::string &msg);
|
: isLoaded(false)
|
||||||
|
{ }
|
||||||
|
|
||||||
/// Read header information from the input source
|
/// Open an archive file.
|
||||||
void readHeader();
|
void open(const std::string &file);
|
||||||
|
|
||||||
/// Get the index of a given file name, or -1 if not found
|
/* -----------------------------------
|
||||||
int getIndex(const char *str) const;
|
* Archive file routines
|
||||||
|
* -----------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
public:
|
/// Check if a file exists
|
||||||
|
bool exists(const char *file) const
|
||||||
|
{ return getIndex(file) != -1; }
|
||||||
|
|
||||||
/* -----------------------------------
|
/** Open a file contained in the archive. Throws an exception if the
|
||||||
* BSA management methods
|
file doesn't exist.
|
||||||
* -----------------------------------
|
*/
|
||||||
*/
|
Ogre::DataStreamPtr getFile(const char *file);
|
||||||
|
|
||||||
BSAFile()
|
/// Get a list of all files
|
||||||
: input(), isLoaded(false) {}
|
const FileList &getList() const
|
||||||
|
|
||||||
/// Open an archive file.
|
|
||||||
void open(const std::string &file);
|
|
||||||
|
|
||||||
/** Open an archive from a generic stream. The 'name' parameter is
|
|
||||||
used for error messages.
|
|
||||||
*/
|
|
||||||
void open(Mangle::Stream::StreamPtr inp, const std::string &name);
|
|
||||||
|
|
||||||
/* -----------------------------------
|
|
||||||
* Archive file routines
|
|
||||||
* -----------------------------------
|
|
||||||
*/
|
|
||||||
|
|
||||||
/// Check if a file exists
|
|
||||||
bool exists(const char *file) const { return getIndex(file) != -1; }
|
|
||||||
|
|
||||||
/** Open a file contained in the archive. Throws an exception if the
|
|
||||||
file doesn't exist.
|
|
||||||
|
|
||||||
NOTE: All files opened from one archive will share a common file
|
|
||||||
handle. This is NOT thread safe.
|
|
||||||
*/
|
|
||||||
Mangle::Stream::StreamPtr getFile(const char *file);
|
|
||||||
|
|
||||||
/// Get a list of all files
|
|
||||||
const FileList &getList() const
|
|
||||||
{ return files; }
|
{ return files; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ void ESMReader::restoreContext(const ESM_Context &rc)
|
||||||
|
|
||||||
void ESMReader::close()
|
void ESMReader::close()
|
||||||
{
|
{
|
||||||
mEsm.reset();
|
mEsm.setNull();
|
||||||
mCtx.filename.clear();
|
mCtx.filename.clear();
|
||||||
mCtx.leftFile = 0;
|
mCtx.leftFile = 0;
|
||||||
mCtx.leftRec = 0;
|
mCtx.leftRec = 0;
|
||||||
|
@ -37,7 +37,7 @@ void ESMReader::close()
|
||||||
mCtx.subName.val = 0;
|
mCtx.subName.val = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESMReader::openRaw(Mangle::Stream::StreamPtr _esm, const std::string &name)
|
void ESMReader::openRaw(Ogre::DataStreamPtr _esm, const std::string &name)
|
||||||
{
|
{
|
||||||
close();
|
close();
|
||||||
mEsm = _esm;
|
mEsm = _esm;
|
||||||
|
@ -57,7 +57,7 @@ void ESMReader::openRaw(Mangle::Stream::StreamPtr _esm, const std::string &name)
|
||||||
mSpf = SF_Other;
|
mSpf = SF_Other;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESMReader::open(Mangle::Stream::StreamPtr _esm, const std::string &name)
|
void ESMReader::open(Ogre::DataStreamPtr _esm, const std::string &name)
|
||||||
{
|
{
|
||||||
openRaw(_esm, name);
|
openRaw(_esm, name);
|
||||||
|
|
||||||
|
@ -107,14 +107,16 @@ void ESMReader::open(Mangle::Stream::StreamPtr _esm, const std::string &name)
|
||||||
|
|
||||||
void ESMReader::open(const std::string &file)
|
void ESMReader::open(const std::string &file)
|
||||||
{
|
{
|
||||||
using namespace Mangle::Stream;
|
std::ifstream *stream = new std::ifstream(file.c_str(), std::ios_base::binary);
|
||||||
open(StreamPtr(new FileStream(file)), file);
|
// Ogre will delete the stream for us
|
||||||
|
open(Ogre::DataStreamPtr(new Ogre::FileStreamDataStream(stream)), file);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESMReader::openRaw(const std::string &file)
|
void ESMReader::openRaw(const std::string &file)
|
||||||
{
|
{
|
||||||
using namespace Mangle::Stream;
|
std::ifstream *stream = new std::ifstream(file.c_str(), std::ios_base::binary);
|
||||||
openRaw(StreamPtr(new FileStream(file)), file);
|
// Ogre will delete the stream for us
|
||||||
|
openRaw(Ogre::DataStreamPtr(new Ogre::FileStreamDataStream(stream)), file);
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t ESMReader::getHNLong(const char *name)
|
int64_t ESMReader::getHNLong(const char *name)
|
||||||
|
@ -339,7 +341,7 @@ void ESMReader::fail(const std::string &msg)
|
||||||
ss << "\n File: " << mCtx.filename;
|
ss << "\n File: " << mCtx.filename;
|
||||||
ss << "\n Record: " << mCtx.recName.toString();
|
ss << "\n Record: " << mCtx.recName.toString();
|
||||||
ss << "\n Subrecord: " << mCtx.subName.toString();
|
ss << "\n Subrecord: " << mCtx.subName.toString();
|
||||||
if (mEsm != NULL)
|
if (!mEsm.isNull())
|
||||||
ss << "\n Offset: 0x" << hex << mEsm->tell();
|
ss << "\n Offset: 0x" << hex << mEsm->tell();
|
||||||
throw std::runtime_error(ss.str());
|
throw std::runtime_error(ss.str());
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,8 +11,8 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
#include <libs/mangle/stream/stream.hpp>
|
#include <OgreDataStream.h>
|
||||||
#include <libs/mangle/stream/servers/file_stream.hpp>
|
|
||||||
#include <components/misc/stringops.hpp>
|
#include <components/misc/stringops.hpp>
|
||||||
|
|
||||||
#include <components/to_utf8/to_utf8.hpp>
|
#include <components/to_utf8/to_utf8.hpp>
|
||||||
|
@ -183,11 +183,11 @@ public:
|
||||||
|
|
||||||
/// Raw opening. Opens the file and sets everything up but doesn't
|
/// Raw opening. Opens the file and sets everything up but doesn't
|
||||||
/// parse the header.
|
/// parse the header.
|
||||||
void openRaw(Mangle::Stream::StreamPtr _esm, const std::string &name);
|
void openRaw(Ogre::DataStreamPtr _esm, const std::string &name);
|
||||||
|
|
||||||
/// Load ES file from a new stream, parses the header. Closes the
|
/// Load ES file from a new stream, parses the header. Closes the
|
||||||
/// currently open file first, if any.
|
/// currently open file first, if any.
|
||||||
void open(Mangle::Stream::StreamPtr _esm, const std::string &name);
|
void open(Ogre::DataStreamPtr _esm, const std::string &name);
|
||||||
|
|
||||||
void open(const std::string &file);
|
void open(const std::string &file);
|
||||||
|
|
||||||
|
@ -354,7 +354,7 @@ public:
|
||||||
void setEncoding(const std::string& encoding);
|
void setEncoding(const std::string& encoding);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Mangle::Stream::StreamPtr mEsm;
|
Ogre::DataStreamPtr mEsm;
|
||||||
|
|
||||||
ESM_Context mCtx;
|
ESM_Context mCtx;
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,6 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
|
|
||||||
#include <libs/mangle/vfs/servers/ogre_vfs.hpp>
|
|
||||||
#include "../nif/nif_file.hpp"
|
#include "../nif/nif_file.hpp"
|
||||||
#include "../nif/node.hpp"
|
#include "../nif/node.hpp"
|
||||||
#include "../nif/data.hpp"
|
#include "../nif/data.hpp"
|
||||||
|
|
|
@ -8,41 +8,7 @@
|
||||||
|
|
||||||
using namespace Terrain;
|
using namespace Terrain;
|
||||||
|
|
||||||
static class ESMLandStream : public Mangle::Stream
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ESMLandStream(ESM::Land *l, ESM::ESMReader &r)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
bool ESMLandFactory::has(int x, int y)
|
bool ESMLandFactory::has(int x, int y)
|
||||||
{
|
{
|
||||||
return store.landscapes.has(x,y);
|
return store.landscapes.has(x,y);
|
||||||
}
|
}
|
||||||
|
|
||||||
LandDataPtr get(int x, int y, LandInfo &info)
|
|
||||||
{
|
|
||||||
assert(has(x,y));
|
|
||||||
|
|
||||||
// Set up the info
|
|
||||||
info.grid = LGT_Quadratic;
|
|
||||||
info.data = LDT_Float;
|
|
||||||
|
|
||||||
const float SIZE = 8192; // CHECK
|
|
||||||
|
|
||||||
info.xsize = SIZE;
|
|
||||||
info.ysize = SIZE;
|
|
||||||
info.numx = 65;
|
|
||||||
info.numy = 65;
|
|
||||||
info.xoffset = SIZE*x;
|
|
||||||
info.yoffset = SIZE*y;
|
|
||||||
|
|
||||||
// Get the Land struct from store
|
|
||||||
ESM::Land* land = store.landscapes.find(x,y);
|
|
||||||
assert(land->hasData);
|
|
||||||
|
|
||||||
// Create a stream for the data and return it.
|
|
||||||
LandDataPtr ptr(new ESMLandStream(land, reader));
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
|
@ -32,10 +32,6 @@ namespace Terrain
|
||||||
|
|
||||||
// True if this factory has any data for the given grid cell.
|
// True if this factory has any data for the given grid cell.
|
||||||
bool has(int x, int y);
|
bool has(int x, int y);
|
||||||
|
|
||||||
// Return stream to data for this cell. Additional data about the
|
|
||||||
// landscape is returned through the LandInfo struct.
|
|
||||||
LandDataPtr get(int x, int y, LandInfo &info);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
#ifndef TERRAIN_LAND_FACTORY_H
|
#ifndef TERRAIN_LAND_FACTORY_H
|
||||||
#define TERRAIN_LAND_FACTORY_H
|
#define TERRAIN_LAND_FACTORY_H
|
||||||
|
|
||||||
#include <mangle/stream/stream.hpp>
|
|
||||||
|
|
||||||
namespace Terrain
|
namespace Terrain
|
||||||
{
|
{
|
||||||
enum LandInfoGridType
|
enum LandInfoGridType
|
||||||
|
@ -32,12 +30,6 @@ namespace Terrain
|
||||||
float xoffset, yoffset;
|
float xoffset, yoffset;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* We use normal streams for data. This allows us to just pass (for
|
|
||||||
example) a file stream as height map input later, with no extra
|
|
||||||
fuzz.
|
|
||||||
*/
|
|
||||||
typedef Mangle::Stream::StreamPtr LandDataPtr;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Factory class that provides streams to land data cells. Each
|
Factory class that provides streams to land data cells. Each
|
||||||
"cell" has a unique integer coordinate in the plane.
|
"cell" has a unique integer coordinate in the plane.
|
||||||
|
@ -46,10 +38,6 @@ namespace Terrain
|
||||||
{
|
{
|
||||||
// True if this factory has any data for the given grid cell.
|
// True if this factory has any data for the given grid cell.
|
||||||
virtual bool has(int x, int y) = 0;
|
virtual bool has(int x, int y) = 0;
|
||||||
|
|
||||||
// Return stream to data for this cell. Additional data about the
|
|
||||||
// landscape is returned through the LandInfo struct.
|
|
||||||
virtual LandDataPtr get(int x, int y, LandInfo &info) = 0;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
#include "audiere_file.hpp"
|
|
||||||
|
|
||||||
using namespace audiere;
|
|
||||||
using namespace Mangle::Stream;
|
|
||||||
|
|
||||||
bool AudiereFile::seek(int pos, SeekMode mode)
|
|
||||||
{
|
|
||||||
assert(inp->isSeekable);
|
|
||||||
assert(inp->hasPosition);
|
|
||||||
|
|
||||||
size_t newPos;
|
|
||||||
|
|
||||||
switch(mode)
|
|
||||||
{
|
|
||||||
case BEGIN: newPos = pos; break;
|
|
||||||
case CURRENT: newPos = pos+tell(); break;
|
|
||||||
case END:
|
|
||||||
// Seeking from the end. This requires that we're able to get
|
|
||||||
// the entire size of the stream. The pos also has to be
|
|
||||||
// non-positive.
|
|
||||||
assert(inp->hasSize);
|
|
||||||
assert(pos <= 0);
|
|
||||||
newPos = inp->size() + pos;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(0 && "invalid seek mode");
|
|
||||||
}
|
|
||||||
|
|
||||||
inp->seek(newPos);
|
|
||||||
return inp->tell() == newPos;
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
#ifndef MANGLE_STREAM_AUDIERECLIENT_H
|
|
||||||
#define MANGLE_STREAM_AUDIERECLIENT_H
|
|
||||||
|
|
||||||
#include <audiere.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include "../stream.hpp"
|
|
||||||
|
|
||||||
namespace Mangle {
|
|
||||||
namespace Stream {
|
|
||||||
|
|
||||||
/** @brief An Audiere::File that wraps a Mangle::Stream input.
|
|
||||||
|
|
||||||
This lets Audiere read sound files from any generic archive or
|
|
||||||
file manager that supports Mangle streams.
|
|
||||||
*/
|
|
||||||
class AudiereFile : public audiere::RefImplementation<audiere::File>
|
|
||||||
{
|
|
||||||
StreamPtr inp;
|
|
||||||
|
|
||||||
public:
|
|
||||||
AudiereFile(StreamPtr _inp)
|
|
||||||
: inp(_inp) {}
|
|
||||||
|
|
||||||
/// Read 'count' bytes, return bytes successfully read
|
|
||||||
int ADR_CALL read(void *buf, int count)
|
|
||||||
{ return inp->read(buf,count); }
|
|
||||||
|
|
||||||
/// Seek, relative to specified seek mode. Returns true if successful.
|
|
||||||
bool ADR_CALL seek(int pos, audiere::File::SeekMode mode);
|
|
||||||
|
|
||||||
/// Get current position
|
|
||||||
int ADR_CALL tell()
|
|
||||||
{ assert(inp->hasPosition); return inp->tell(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
}} // namespaces
|
|
||||||
#endif
|
|
|
@ -1,221 +0,0 @@
|
||||||
#include "io_stream.hpp"
|
|
||||||
|
|
||||||
// This seems to work
|
|
||||||
#ifndef EOF
|
|
||||||
#define EOF -1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using namespace Mangle::Stream;
|
|
||||||
|
|
||||||
#define BSIZE 1024
|
|
||||||
|
|
||||||
// Streambuf for normal stream reading
|
|
||||||
class _istreambuf : public std::streambuf
|
|
||||||
{
|
|
||||||
StreamPtr client;
|
|
||||||
char buf[BSIZE];
|
|
||||||
|
|
||||||
public:
|
|
||||||
_istreambuf(StreamPtr strm) : client(strm)
|
|
||||||
{
|
|
||||||
// Make sure we picked the right class
|
|
||||||
assert(client->isReadable);
|
|
||||||
assert(!client->hasPtr);
|
|
||||||
|
|
||||||
// Tell streambuf to delegate reading operations to underflow()
|
|
||||||
setg(NULL,NULL,NULL);
|
|
||||||
|
|
||||||
// Disallow writing
|
|
||||||
setp(NULL,NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Underflow is called when there is no more info to read in the
|
|
||||||
input buffer. We need to refill buf with new data (if any), and
|
|
||||||
set up the internal pointers with setg() to reflect the new
|
|
||||||
state.
|
|
||||||
*/
|
|
||||||
int underflow()
|
|
||||||
{
|
|
||||||
// Read some more data
|
|
||||||
size_t read = client->read(buf, BSIZE);
|
|
||||||
assert(read <= BSIZE);
|
|
||||||
|
|
||||||
// If we're out of data, then EOF
|
|
||||||
if(read == 0)
|
|
||||||
return EOF;
|
|
||||||
|
|
||||||
// Otherwise, set up input buffer
|
|
||||||
setg(buf, buf, buf+read);
|
|
||||||
|
|
||||||
// Return the first char
|
|
||||||
return *((unsigned char*)buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Seek stream, if the source supports it. Ignores the second
|
|
||||||
// parameter as Mangle doesn't separate input and output pointers.
|
|
||||||
std::streampos seekpos(std::streampos pos, std::ios_base::openmode = std::ios_base::in)
|
|
||||||
{
|
|
||||||
// Does this stream know how to seek?
|
|
||||||
if(!client->isSeekable || !client->hasPosition)
|
|
||||||
// If not, signal an error.
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
// Set stream position and reset the buffer.
|
|
||||||
client->seek(pos);
|
|
||||||
setg(NULL,NULL,NULL);
|
|
||||||
|
|
||||||
return client->tell();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Streambuf optimized for pointer-based input streams
|
|
||||||
class _ptrstreambuf : public std::streambuf
|
|
||||||
{
|
|
||||||
StreamPtr client;
|
|
||||||
|
|
||||||
public:
|
|
||||||
_ptrstreambuf(StreamPtr strm) : client(strm)
|
|
||||||
{
|
|
||||||
// Make sure we picked the right class
|
|
||||||
assert(client->isReadable);
|
|
||||||
assert(client->hasPtr);
|
|
||||||
|
|
||||||
// seekpos() does all the work
|
|
||||||
seekpos(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Underflow is only called when we're at the end of the file
|
|
||||||
int underflow() { return EOF; }
|
|
||||||
|
|
||||||
// Seek to a new position within the memory stream. This bypasses
|
|
||||||
// client->seek() entirely so isSeekable doesn't have to be set.
|
|
||||||
std::streampos seekpos(std::streampos pos, std::ios_base::openmode = std::ios_base::in)
|
|
||||||
{
|
|
||||||
// All pointer streams need a size
|
|
||||||
assert(client->hasSize);
|
|
||||||
|
|
||||||
// Figure out how much will be left of the stream after seeking
|
|
||||||
size_t size = client->size() - pos;
|
|
||||||
|
|
||||||
// Get a pointer
|
|
||||||
char* ptr = (char*)client->getPtr(pos,size);
|
|
||||||
|
|
||||||
// And use it
|
|
||||||
setg(ptr,ptr,ptr+size);
|
|
||||||
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Streambuf for stream writing
|
|
||||||
class _ostreambuf : public std::streambuf
|
|
||||||
{
|
|
||||||
StreamPtr client;
|
|
||||||
char buf[BSIZE];
|
|
||||||
|
|
||||||
public:
|
|
||||||
_ostreambuf(StreamPtr strm) : client(strm)
|
|
||||||
{
|
|
||||||
// Make sure we picked the right class
|
|
||||||
assert(client->isWritable);
|
|
||||||
|
|
||||||
// Inform streambuf about our nice buffer
|
|
||||||
setp(buf, buf+BSIZE);
|
|
||||||
|
|
||||||
// Disallow reading
|
|
||||||
setg(NULL,NULL,NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Sync means to flush (write) all current data to the output
|
|
||||||
stream. It will also set up the entire output buffer to be usable
|
|
||||||
again.
|
|
||||||
*/
|
|
||||||
int sync()
|
|
||||||
{
|
|
||||||
// Get the number of bytes that streambuf wants us to write
|
|
||||||
int num = pptr() - pbase();
|
|
||||||
assert(num >= 0);
|
|
||||||
|
|
||||||
// Is there any work to do?
|
|
||||||
if(num == 0) return 0;
|
|
||||||
|
|
||||||
if((int)client->write(pbase(), num) != num)
|
|
||||||
// Inform caller that writing failed
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
// Reset output buffer pointers
|
|
||||||
setp(buf, buf+BSIZE);
|
|
||||||
|
|
||||||
// No error
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Called whenever the output buffer is full.
|
|
||||||
*/
|
|
||||||
int overflow(int c)
|
|
||||||
{
|
|
||||||
// First, write all existing data
|
|
||||||
if(sync()) return EOF;
|
|
||||||
|
|
||||||
// Put the requested character in the next round of output
|
|
||||||
if(c != EOF)
|
|
||||||
{
|
|
||||||
*pptr() = c;
|
|
||||||
pbump(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// No error
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Seek stream, if the source supports it.
|
|
||||||
std::streampos seekpos(std::streampos pos, std::ios_base::openmode = std::ios_base::out)
|
|
||||||
{
|
|
||||||
if(!client->isSeekable || !client->hasPosition)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
// Flush data and reset buffers
|
|
||||||
sync();
|
|
||||||
|
|
||||||
// Set stream position
|
|
||||||
client->seek(pos);
|
|
||||||
|
|
||||||
return client->tell();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
MangleIStream::MangleIStream(StreamPtr inp)
|
|
||||||
: std::istream(NULL)
|
|
||||||
{
|
|
||||||
assert(inp->isReadable);
|
|
||||||
|
|
||||||
// Pick the right streambuf implementation based on whether the
|
|
||||||
// input supports pointers or not.
|
|
||||||
if(inp->hasPtr)
|
|
||||||
buf = new _ptrstreambuf(inp);
|
|
||||||
else
|
|
||||||
buf = new _istreambuf(inp);
|
|
||||||
|
|
||||||
rdbuf(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
MangleIStream::~MangleIStream()
|
|
||||||
{
|
|
||||||
delete buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
MangleOStream::MangleOStream(StreamPtr out)
|
|
||||||
: std::ostream(NULL)
|
|
||||||
{
|
|
||||||
assert(out->isWritable);
|
|
||||||
buf = new _ostreambuf(out);
|
|
||||||
|
|
||||||
rdbuf(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
MangleOStream::~MangleOStream()
|
|
||||||
{
|
|
||||||
// Make sure we don't have lingering data on exit
|
|
||||||
flush();
|
|
||||||
delete buf;
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
#ifndef MANGLE_STREAM_IOSTREAM_H
|
|
||||||
#define MANGLE_STREAM_IOSTREAM_H
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include "../stream.hpp"
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
namespace Mangle {
|
|
||||||
namespace Stream {
|
|
||||||
|
|
||||||
/** This file contains classes for wrapping an std::istream or
|
|
||||||
std::ostream around a Mangle::Stream.
|
|
||||||
|
|
||||||
This allows you to use Mangle streams in places that require std
|
|
||||||
streams.
|
|
||||||
|
|
||||||
This is much easier than trying to make your own custom streams
|
|
||||||
into iostreams. The std::iostream interface is horrible and NOT
|
|
||||||
designed for easy subclassing. Create a Mangle::Stream instead,
|
|
||||||
and use this wrapper.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// An istream wrapping a readable Mangle::Stream. Has extra
|
|
||||||
// optimizations for pointer-based streams.
|
|
||||||
class MangleIStream : public std::istream
|
|
||||||
{
|
|
||||||
std::streambuf *buf;
|
|
||||||
public:
|
|
||||||
MangleIStream(StreamPtr inp);
|
|
||||||
~MangleIStream();
|
|
||||||
};
|
|
||||||
|
|
||||||
// An ostream wrapping a writable Mangle::Stream.
|
|
||||||
class MangleOStream : public std::ostream
|
|
||||||
{
|
|
||||||
std::streambuf *buf;
|
|
||||||
public:
|
|
||||||
MangleOStream(StreamPtr inp);
|
|
||||||
~MangleOStream();
|
|
||||||
};
|
|
||||||
|
|
||||||
}} // namespaces
|
|
||||||
#endif
|
|
|
@ -1,68 +0,0 @@
|
||||||
#ifndef MANGLE_STREAM_OGRECLIENT_H
|
|
||||||
#define MANGLE_STREAM_OGRECLIENT_H
|
|
||||||
|
|
||||||
#include <OgreDataStream.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include "../stream.hpp"
|
|
||||||
|
|
||||||
namespace Mangle {
|
|
||||||
namespace Stream {
|
|
||||||
|
|
||||||
/** An OGRE DataStream that wraps a Mangle::Stream input.
|
|
||||||
|
|
||||||
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 Mangle2OgreStream : public Ogre::DataStream
|
|
||||||
{
|
|
||||||
StreamPtr inp;
|
|
||||||
|
|
||||||
void init()
|
|
||||||
{
|
|
||||||
// Get the size, if possible
|
|
||||||
if(inp->hasSize)
|
|
||||||
mSize = inp->size();
|
|
||||||
|
|
||||||
// Allow writing if inp supports it
|
|
||||||
if(inp->isWritable)
|
|
||||||
mAccess |= Ogre::DataStream::WRITE;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
/// Constructor without name
|
|
||||||
Mangle2OgreStream(StreamPtr _inp)
|
|
||||||
: inp(_inp) { init(); }
|
|
||||||
|
|
||||||
/// Constructor for a named data stream
|
|
||||||
Mangle2OgreStream(const Ogre::String &name, StreamPtr _inp)
|
|
||||||
: Ogre::DataStream(name), inp(_inp) { init(); }
|
|
||||||
|
|
||||||
// Only implement the DataStream functions we have to implement
|
|
||||||
|
|
||||||
size_t read(void *buf, size_t count)
|
|
||||||
{ return inp->read(buf,count); }
|
|
||||||
|
|
||||||
size_t write(const void *buf, size_t count)
|
|
||||||
{ assert(inp->isWritable); return inp->write(buf,count); }
|
|
||||||
|
|
||||||
void skip(long count)
|
|
||||||
{
|
|
||||||
assert(inp->isSeekable && inp->hasPosition);
|
|
||||||
inp->seek(inp->tell() + count);
|
|
||||||
}
|
|
||||||
|
|
||||||
void seek(size_t pos)
|
|
||||||
{ assert(inp->isSeekable); inp->seek(pos); }
|
|
||||||
|
|
||||||
size_t tell() const
|
|
||||||
{ assert(inp->hasPosition); return inp->tell(); }
|
|
||||||
|
|
||||||
bool eof() const { return inp->eof(); }
|
|
||||||
|
|
||||||
/// Does nothing
|
|
||||||
void close() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
}} // namespaces
|
|
||||||
#endif
|
|
|
@ -1,74 +0,0 @@
|
||||||
#ifndef MANGLE_STREAM_BUFFER_H
|
|
||||||
#define MANGLE_STREAM_BUFFER_H
|
|
||||||
|
|
||||||
#include "../servers/memory_stream.hpp"
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace Mangle {
|
|
||||||
namespace Stream {
|
|
||||||
|
|
||||||
/** A Stream that reads another Stream into a buffer, and serves it as
|
|
||||||
a MemoryStream. Might be expanded with other capabilities later.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class BufferStream : public MemoryStream
|
|
||||||
{
|
|
||||||
std::vector<char> buffer;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/*
|
|
||||||
input = stream to copy
|
|
||||||
ADD = each read increment (for streams without size())
|
|
||||||
*/
|
|
||||||
BufferStream(StreamPtr input, size_t ADD = 32*1024)
|
|
||||||
{
|
|
||||||
assert(input);
|
|
||||||
|
|
||||||
// Allocate memory, read the stream into it. Then call set()
|
|
||||||
if(input->hasSize)
|
|
||||||
{
|
|
||||||
// We assume that we can get the position as well
|
|
||||||
assert(input->hasPosition);
|
|
||||||
|
|
||||||
// Calculate how much is left of the stream
|
|
||||||
size_t left = input->size() - input->tell();
|
|
||||||
|
|
||||||
// Allocate the buffer and fill it
|
|
||||||
buffer.resize(left);
|
|
||||||
input->read(&buffer[0], left);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// We DON'T know how big the stream is. We'll have to read
|
|
||||||
// it in increments.
|
|
||||||
size_t len=0, newlen;
|
|
||||||
|
|
||||||
while(!input->eof())
|
|
||||||
{
|
|
||||||
// Read one block
|
|
||||||
newlen = len + ADD;
|
|
||||||
buffer.resize(newlen);
|
|
||||||
size_t read = input->read(&buffer[len], ADD);
|
|
||||||
|
|
||||||
// Increase the total length
|
|
||||||
len += read;
|
|
||||||
|
|
||||||
// If we read less than expected, we should be at the
|
|
||||||
// end of the stream
|
|
||||||
assert(read == ADD || (read < ADD && input->eof()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Downsize to match the real length
|
|
||||||
buffer.resize(len);
|
|
||||||
}
|
|
||||||
|
|
||||||
// After the buffer has been filled, set up our MemoryStream
|
|
||||||
// ancestor to reference it.
|
|
||||||
set(&buffer[0], buffer.size());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef boost::shared_ptr<BufferStream> BufferStreamPtr;
|
|
||||||
|
|
||||||
}} // namespaces
|
|
||||||
#endif
|
|
|
@ -1,46 +0,0 @@
|
||||||
#ifndef MANGLE_STREAM_FILTER_H
|
|
||||||
#define MANGLE_STREAM_FILTER_H
|
|
||||||
|
|
||||||
#include "../stream.hpp"
|
|
||||||
|
|
||||||
namespace Mangle {
|
|
||||||
namespace Stream {
|
|
||||||
|
|
||||||
/** A stream that filters another stream with no changes. Intended as
|
|
||||||
a base class for other filters.
|
|
||||||
*/
|
|
||||||
class PureFilter : public Stream
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
StreamPtr src;
|
|
||||||
|
|
||||||
public:
|
|
||||||
PureFilter() {}
|
|
||||||
PureFilter(StreamPtr _src)
|
|
||||||
{ setStream(_src); }
|
|
||||||
|
|
||||||
void setStream(StreamPtr _src)
|
|
||||||
{
|
|
||||||
src = _src;
|
|
||||||
isSeekable = src->isSeekable;
|
|
||||||
isWritable = src->isWritable;
|
|
||||||
hasPosition = src->hasPosition;
|
|
||||||
hasSize = src->hasSize;
|
|
||||||
hasPtr = src->hasPtr;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t read(void *buf, size_t count) { return src->read(buf, count); }
|
|
||||||
size_t write(const void *buf, size_t count) { return src->write(buf,count); }
|
|
||||||
void flush() { src->flush(); }
|
|
||||||
void seek(size_t pos) { src->seek(pos); }
|
|
||||||
size_t tell() const { return src->tell(); }
|
|
||||||
size_t size() const { return src->size(); }
|
|
||||||
bool eof() const { return src->eof(); }
|
|
||||||
const void *getPtr() { return src->getPtr(); }
|
|
||||||
const void *getPtr(size_t size) { return src->getPtr(size); }
|
|
||||||
const void *getPtr(size_t pos, size_t size)
|
|
||||||
{ return src->getPtr(pos, size); }
|
|
||||||
};
|
|
||||||
|
|
||||||
}} // namespaces
|
|
||||||
#endif
|
|
|
@ -1,101 +0,0 @@
|
||||||
#ifndef MANGLE_STREAM_SLICE_H
|
|
||||||
#define MANGLE_STREAM_SLICE_H
|
|
||||||
|
|
||||||
#include "../stream.hpp"
|
|
||||||
|
|
||||||
namespace Mangle {
|
|
||||||
namespace Stream {
|
|
||||||
|
|
||||||
/** A Stream that represents a subset (called a slice) of another stream.
|
|
||||||
*/
|
|
||||||
class SliceStream : public Stream
|
|
||||||
{
|
|
||||||
StreamPtr src;
|
|
||||||
size_t offset, length, pos;
|
|
||||||
|
|
||||||
public:
|
|
||||||
SliceStream(StreamPtr _src, size_t _offset, size_t _length)
|
|
||||||
: src(_src), offset(_offset), length(_length), pos(0)
|
|
||||||
{
|
|
||||||
assert(src->hasSize);
|
|
||||||
assert(src->isSeekable);
|
|
||||||
|
|
||||||
// Make sure we can actually fit inside the source stream
|
|
||||||
assert(src->size() >= offset+length);
|
|
||||||
|
|
||||||
isSeekable = true;
|
|
||||||
hasPosition = true;
|
|
||||||
hasSize = true;
|
|
||||||
hasPtr = src->hasPtr;
|
|
||||||
isWritable = src->isWritable;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t read(void *buf, size_t count)
|
|
||||||
{
|
|
||||||
// Check that we're not reading past our slice
|
|
||||||
if(count > length-pos)
|
|
||||||
count = length-pos;
|
|
||||||
|
|
||||||
// Seek into place and start reading
|
|
||||||
src->seek(offset+pos);
|
|
||||||
count = src->read(buf, count);
|
|
||||||
|
|
||||||
pos += count;
|
|
||||||
assert(pos <= length);
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note that writing to a slice does not allow you to append data,
|
|
||||||
// you may only overwrite existing data.
|
|
||||||
size_t write(const void *buf, size_t count)
|
|
||||||
{
|
|
||||||
assert(isWritable);
|
|
||||||
// Check that we're not reading past our slice
|
|
||||||
if(count > length-pos)
|
|
||||||
count = length-pos;
|
|
||||||
|
|
||||||
// Seek into place and action
|
|
||||||
src->seek(offset+pos);
|
|
||||||
count = src->write(buf, count);
|
|
||||||
|
|
||||||
pos += count;
|
|
||||||
assert(pos <= length);
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
void seek(size_t _pos)
|
|
||||||
{
|
|
||||||
pos = _pos;
|
|
||||||
if(pos > length) pos = length;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool eof() const { return pos == length; }
|
|
||||||
size_t tell() const { return pos; }
|
|
||||||
size_t size() const { return length; }
|
|
||||||
void flush() { src->flush(); }
|
|
||||||
|
|
||||||
const void *getPtr() { return getPtr(0, length); }
|
|
||||||
const void *getPtr(size_t size)
|
|
||||||
{
|
|
||||||
const void *ptr = getPtr(pos, size);
|
|
||||||
seek(pos+size);
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
const void *getPtr(size_t pos, size_t size)
|
|
||||||
{
|
|
||||||
// Boundry checks on pos and size. Bounding the size is
|
|
||||||
// important even when getting pointers, as the source stream
|
|
||||||
// may use the size parameter for something (such as memory
|
|
||||||
// mapping or buffering.)
|
|
||||||
if(pos > length) pos = length;
|
|
||||||
if(pos+size > length) size = length-pos;
|
|
||||||
|
|
||||||
// Ask the source to kindly give us a pointer
|
|
||||||
return src->getPtr(offset+pos, size);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef boost::shared_ptr<SliceStream> SliceStreamPtr;
|
|
||||||
|
|
||||||
}} // namespaces
|
|
||||||
#endif
|
|
|
@ -1,32 +0,0 @@
|
||||||
#ifndef MANGLE_STREAM_FILESERVER_H
|
|
||||||
#define MANGLE_STREAM_FILESERVER_H
|
|
||||||
|
|
||||||
#include "std_stream.hpp"
|
|
||||||
#include <fstream>
|
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
namespace Mangle {
|
|
||||||
namespace Stream {
|
|
||||||
|
|
||||||
/** Very simple file input stream, based on std::ifstream
|
|
||||||
*/
|
|
||||||
class FileStream : public StdStream
|
|
||||||
{
|
|
||||||
std::ifstream file;
|
|
||||||
|
|
||||||
public:
|
|
||||||
FileStream(const std::string &name)
|
|
||||||
: StdStream(&file)
|
|
||||||
{
|
|
||||||
file.open(name.c_str(), std::ios::binary);
|
|
||||||
|
|
||||||
if(file.fail())
|
|
||||||
throw std::runtime_error("FileStream: failed to open file " + name);
|
|
||||||
}
|
|
||||||
~FileStream() { file.close(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef boost::shared_ptr<FileStream> FileStreamPtr;
|
|
||||||
|
|
||||||
}} // namespaces
|
|
||||||
#endif
|
|
|
@ -1,116 +0,0 @@
|
||||||
#ifndef MANGLE_STREAM_MEMSERVER_H
|
|
||||||
#define MANGLE_STREAM_MEMSERVER_H
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include "../stream.hpp"
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
namespace Mangle {
|
|
||||||
namespace Stream {
|
|
||||||
|
|
||||||
// Do this before the class declaration, since the class itself
|
|
||||||
// uses it.
|
|
||||||
class MemoryStream;
|
|
||||||
typedef boost::shared_ptr<MemoryStream> MemoryStreamPtr;
|
|
||||||
|
|
||||||
/** A Stream wrapping a memory buffer
|
|
||||||
|
|
||||||
This will create a fully seekable stream out of any pointer/length
|
|
||||||
pair you give it.
|
|
||||||
*/
|
|
||||||
class MemoryStream : public Stream
|
|
||||||
{
|
|
||||||
const void *data;
|
|
||||||
size_t length, pos;
|
|
||||||
|
|
||||||
public:
|
|
||||||
MemoryStream(const void *ptr, size_t len)
|
|
||||||
: data(ptr), length(len), pos(0)
|
|
||||||
{
|
|
||||||
isSeekable = true;
|
|
||||||
hasPosition = true;
|
|
||||||
hasSize = true;
|
|
||||||
hasPtr = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryStream()
|
|
||||||
: data(NULL), length(0), pos(0)
|
|
||||||
{
|
|
||||||
isSeekable = true;
|
|
||||||
hasPosition = true;
|
|
||||||
hasSize = true;
|
|
||||||
hasPtr = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t read(void *buf, size_t count)
|
|
||||||
{
|
|
||||||
assert(data != NULL);
|
|
||||||
assert(pos <= length);
|
|
||||||
|
|
||||||
// Don't read more than we have
|
|
||||||
if(count > (length - pos))
|
|
||||||
count = length - pos;
|
|
||||||
|
|
||||||
// Copy data
|
|
||||||
if(count)
|
|
||||||
memcpy(buf, ((char*)data)+pos, count);
|
|
||||||
|
|
||||||
// aaand remember to increase the count
|
|
||||||
pos += count;
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
void seek(size_t _pos)
|
|
||||||
{
|
|
||||||
pos = _pos;
|
|
||||||
if(pos > length)
|
|
||||||
pos = length;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t tell() const { return pos; }
|
|
||||||
size_t size() const { return length; }
|
|
||||||
bool eof() const { return pos == length; }
|
|
||||||
|
|
||||||
const void *getPtr() { return data; }
|
|
||||||
const void *getPtr(size_t size)
|
|
||||||
{
|
|
||||||
// This variant of getPtr must move the position pointer
|
|
||||||
size_t opos = pos;
|
|
||||||
pos += size;
|
|
||||||
if(pos > length) pos = length;
|
|
||||||
return ((char*)data)+opos;
|
|
||||||
}
|
|
||||||
const void *getPtr(size_t pos, size_t size)
|
|
||||||
{
|
|
||||||
if(pos > length) pos = length;
|
|
||||||
return ((char*)data)+pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
// New members in MemoryStream:
|
|
||||||
|
|
||||||
/// Set a new buffer and length. This will rewind the position to zero.
|
|
||||||
void set(const void* _data, size_t _length)
|
|
||||||
{
|
|
||||||
data = _data;
|
|
||||||
length = _length;
|
|
||||||
pos = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Clone this memory stream
|
|
||||||
/** Make a new stream of the same buffer. If setPos is true, we also
|
|
||||||
set the clone's position to be the same as ours.
|
|
||||||
|
|
||||||
No memory is copied during this operation, the new stream is
|
|
||||||
just another 'view' into the same shared memory buffer.
|
|
||||||
*/
|
|
||||||
MemoryStreamPtr clone(bool setPos=false) const
|
|
||||||
{
|
|
||||||
MemoryStreamPtr res(new MemoryStream(data, length));
|
|
||||||
if(setPos) res->seek(pos);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}} // namespaces
|
|
||||||
#endif
|
|
|
@ -1,37 +0,0 @@
|
||||||
#ifndef MANGLE_STREAM_OGRESERVER_H
|
|
||||||
#define MANGLE_STREAM_OGRESERVER_H
|
|
||||||
|
|
||||||
#include <OgreDataStream.h>
|
|
||||||
|
|
||||||
namespace Mangle {
|
|
||||||
namespace Stream {
|
|
||||||
|
|
||||||
/** A Stream wrapping an OGRE DataStream.
|
|
||||||
|
|
||||||
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 OgreStream : public Stream
|
|
||||||
{
|
|
||||||
Ogre::DataStreamPtr inp;
|
|
||||||
|
|
||||||
public:
|
|
||||||
OgreStream(Ogre::DataStreamPtr _inp) : inp(_inp)
|
|
||||||
{
|
|
||||||
isSeekable = true;
|
|
||||||
hasPosition = true;
|
|
||||||
hasSize = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t read(void *buf, size_t count) { return inp->read(buf,count); }
|
|
||||||
void seek(size_t pos) { inp->seek(pos); }
|
|
||||||
size_t tell() const { return inp->tell(); }
|
|
||||||
size_t size() const { return inp->size(); }
|
|
||||||
bool eof() const { return inp->eof(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef boost::shared_ptr<OgreStream> OgreStreamPtr;
|
|
||||||
|
|
||||||
}} // namespaces
|
|
||||||
#endif
|
|
|
@ -1,41 +0,0 @@
|
||||||
#ifndef MANGLE_OSTREAM_FILESERVER_H
|
|
||||||
#define MANGLE_OSTREAM_FILESERVER_H
|
|
||||||
|
|
||||||
#include "std_ostream.hpp"
|
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
namespace Mangle {
|
|
||||||
namespace Stream {
|
|
||||||
|
|
||||||
/** File stream based on std::ofstream, only supports writing.
|
|
||||||
*/
|
|
||||||
class OutFileStream : public StdOStream
|
|
||||||
{
|
|
||||||
std::ofstream file;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
By default we overwrite the file. If append=true, then we will
|
|
||||||
open an existing file and seek to the end instead.
|
|
||||||
*/
|
|
||||||
OutFileStream(const std::string &name, bool append=false)
|
|
||||||
: StdOStream(&file)
|
|
||||||
{
|
|
||||||
std::ios::openmode mode = std::ios::binary;
|
|
||||||
if(append)
|
|
||||||
mode |= std::ios::app;
|
|
||||||
else
|
|
||||||
mode |= std::ios::trunc;
|
|
||||||
|
|
||||||
file.open(name.c_str(), mode);
|
|
||||||
|
|
||||||
if(file.fail())
|
|
||||||
throw std::runtime_error("OutFileStream: failed to open file " + name);
|
|
||||||
}
|
|
||||||
~OutFileStream() { file.close(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef boost::shared_ptr<OutFileStream> OutFileStreamPtr;
|
|
||||||
|
|
||||||
}} // namespaces
|
|
||||||
#endif
|
|
|
@ -1,36 +0,0 @@
|
||||||
#ifndef MANGLE_STREAM_OGRESERVER_H
|
|
||||||
#define MANGLE_STREAM_OGRESERVER_H
|
|
||||||
|
|
||||||
#include <physfs.h>
|
|
||||||
|
|
||||||
namespace Mangle {
|
|
||||||
namespace Stream {
|
|
||||||
|
|
||||||
/// A Stream wrapping a PHYSFS_file stream from the PhysFS library.
|
|
||||||
class PhysFile : public Stream
|
|
||||||
{
|
|
||||||
PHYSFS_file *file;
|
|
||||||
|
|
||||||
public:
|
|
||||||
PhysFile(PHYSFS_file *inp) : file(inp)
|
|
||||||
{
|
|
||||||
isSeekable = true;
|
|
||||||
hasPosition = true;
|
|
||||||
hasSize = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
~PhysFile() { PHYSFS_close(file); }
|
|
||||||
|
|
||||||
size_t read(void *buf, size_t count)
|
|
||||||
{ return PHYSFS_read(file, buf, 1, count); }
|
|
||||||
|
|
||||||
void seek(size_t pos) { PHYSFS_seek(file, pos); }
|
|
||||||
size_t tell() const { return PHYSFS_tell(file); }
|
|
||||||
size_t size() const { return PHYSFS_fileLength(file); }
|
|
||||||
bool eof() const { return PHYSFS_eof(file); }
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef boost::shared_ptr<PhysFile> PhysFilePtr;
|
|
||||||
|
|
||||||
}} // namespaces
|
|
||||||
#endif
|
|
|
@ -1,78 +0,0 @@
|
||||||
#ifndef MANGLE_OSTREAM_STDIOSERVER_H
|
|
||||||
#define MANGLE_OSTREAM_STDIOSERVER_H
|
|
||||||
|
|
||||||
#include "../stream.hpp"
|
|
||||||
#include <iostream>
|
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
namespace Mangle {
|
|
||||||
namespace Stream {
|
|
||||||
|
|
||||||
/** Simple wrapper for std::ostream, only supports output.
|
|
||||||
*/
|
|
||||||
class StdOStream : public Stream
|
|
||||||
{
|
|
||||||
std::ostream *inf;
|
|
||||||
|
|
||||||
static void fail(const std::string &msg)
|
|
||||||
{ throw std::runtime_error("StdOStream: " + msg); }
|
|
||||||
|
|
||||||
public:
|
|
||||||
StdOStream(std::ostream *_inf)
|
|
||||||
: inf(_inf)
|
|
||||||
{
|
|
||||||
isSeekable = true;
|
|
||||||
hasPosition = true;
|
|
||||||
hasSize = true;
|
|
||||||
isWritable = true;
|
|
||||||
isReadable = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t write(const void* buf, size_t len)
|
|
||||||
{
|
|
||||||
inf->write((const char*)buf, len);
|
|
||||||
if(inf->fail())
|
|
||||||
fail("error writing to stream");
|
|
||||||
// Just return len, but that is ok. The only cases where we would
|
|
||||||
// return less than len is when an error occured.
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
void flush()
|
|
||||||
{
|
|
||||||
inf->flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
void seek(size_t pos)
|
|
||||||
{
|
|
||||||
inf->seekp(pos);
|
|
||||||
if(inf->fail())
|
|
||||||
fail("seek error");
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t tell() const
|
|
||||||
// Hack around the fact that ifstream->tellp() isn't const
|
|
||||||
{ return ((StdOStream*)this)->inf->tellp(); }
|
|
||||||
|
|
||||||
size_t size() const
|
|
||||||
{
|
|
||||||
// Use the standard iostream size hack, terrible as it is.
|
|
||||||
std::streampos pos = inf->tellp();
|
|
||||||
inf->seekp(0, std::ios::end);
|
|
||||||
size_t res = inf->tellp();
|
|
||||||
inf->seekp(pos);
|
|
||||||
|
|
||||||
if(inf->fail())
|
|
||||||
fail("could not get stream size");
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool eof() const
|
|
||||||
{ return inf->eof(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef boost::shared_ptr<StdOStream> StdOStreamPtr;
|
|
||||||
|
|
||||||
}} // namespaces
|
|
||||||
#endif
|
|
|
@ -1,70 +0,0 @@
|
||||||
#ifndef MANGLE_STREAM_STDIOSERVER_H
|
|
||||||
#define MANGLE_STREAM_STDIOSERVER_H
|
|
||||||
|
|
||||||
#include "../stream.hpp"
|
|
||||||
#include <iostream>
|
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
namespace Mangle {
|
|
||||||
namespace Stream {
|
|
||||||
|
|
||||||
/** Simple wrapper for std::istream.
|
|
||||||
*/
|
|
||||||
class StdStream : public Stream
|
|
||||||
{
|
|
||||||
std::istream *inf;
|
|
||||||
|
|
||||||
static void fail(const std::string &msg)
|
|
||||||
{ throw std::runtime_error("StdStream: " + msg); }
|
|
||||||
|
|
||||||
public:
|
|
||||||
StdStream(std::istream *_inf)
|
|
||||||
: inf(_inf)
|
|
||||||
{
|
|
||||||
isSeekable = true;
|
|
||||||
hasPosition = true;
|
|
||||||
hasSize = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t read(void* buf, size_t len)
|
|
||||||
{
|
|
||||||
inf->read((char*)buf, len);
|
|
||||||
if(inf->bad())
|
|
||||||
fail("error reading from stream");
|
|
||||||
return inf->gcount();
|
|
||||||
}
|
|
||||||
|
|
||||||
void seek(size_t pos)
|
|
||||||
{
|
|
||||||
inf->clear();
|
|
||||||
inf->seekg(pos);
|
|
||||||
if(inf->fail())
|
|
||||||
fail("seek error");
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t tell() const
|
|
||||||
// Hack around the fact that ifstream->tellg() isn't const
|
|
||||||
{ return ((StdStream*)this)->inf->tellg(); }
|
|
||||||
|
|
||||||
size_t size() const
|
|
||||||
{
|
|
||||||
// Use the standard iostream size hack, terrible as it is.
|
|
||||||
std::streampos pos = inf->tellg();
|
|
||||||
inf->seekg(0, std::ios::end);
|
|
||||||
size_t res = inf->tellg();
|
|
||||||
inf->seekg(pos);
|
|
||||||
|
|
||||||
if(inf->fail())
|
|
||||||
fail("could not get stream size");
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool eof() const
|
|
||||||
{ return inf->eof(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef boost::shared_ptr<StdStream> StdStreamPtr;
|
|
||||||
|
|
||||||
}} // namespaces
|
|
||||||
#endif
|
|
|
@ -1,103 +0,0 @@
|
||||||
#ifndef MANGLE_STREAM_INPUT_H
|
|
||||||
#define MANGLE_STREAM_INPUT_H
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include "../tools/shared_ptr.hpp"
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
namespace Mangle {
|
|
||||||
namespace Stream {
|
|
||||||
|
|
||||||
/// An abstract interface for a stream data.
|
|
||||||
class Stream
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// Feature options. These should be set in the constructor.
|
|
||||||
|
|
||||||
/// If true, seek() works
|
|
||||||
bool isSeekable;
|
|
||||||
|
|
||||||
/// If true, tell() works
|
|
||||||
bool hasPosition;
|
|
||||||
|
|
||||||
/// If true, size() works
|
|
||||||
bool hasSize;
|
|
||||||
|
|
||||||
/// If true, write() works. Writing through pointer operations is
|
|
||||||
/// not (yet) supported.
|
|
||||||
bool isWritable;
|
|
||||||
|
|
||||||
/// If true, read() and eof() works.
|
|
||||||
bool isReadable;
|
|
||||||
|
|
||||||
/// If true, the getPtr() functions work
|
|
||||||
bool hasPtr;
|
|
||||||
|
|
||||||
/// Initialize all bools to false by default, except isReadable.
|
|
||||||
Stream() :
|
|
||||||
isSeekable(false), hasPosition(false), hasSize(false),
|
|
||||||
isWritable(false), isReadable(true), hasPtr(false) {}
|
|
||||||
|
|
||||||
/// Virtual destructor
|
|
||||||
virtual ~Stream() {}
|
|
||||||
|
|
||||||
/** Read a given number of bytes from the stream. Returns the actual
|
|
||||||
number read. If the return value is less than count, then the
|
|
||||||
stream is empty or an error occured. Only required for readable
|
|
||||||
streams.
|
|
||||||
*/
|
|
||||||
virtual size_t read(void* buf, size_t count) { assert(0); return 0; }
|
|
||||||
|
|
||||||
/** Write a given number of bytes from the stream. Semantics is
|
|
||||||
similar to read(). Only valid if isWritable is true.
|
|
||||||
|
|
||||||
The returned value is the number of bytes written. However in
|
|
||||||
most cases, unlike for read(), a write-count less than requested
|
|
||||||
usually indicates an error. The implementation should throw such
|
|
||||||
errors as exceptions rather than expect the caller to handle
|
|
||||||
them.
|
|
||||||
|
|
||||||
Since most implementations do NOT support writing we default to
|
|
||||||
an assert(0) here.
|
|
||||||
*/
|
|
||||||
virtual size_t write(const void *buf, size_t count) { assert(0); return 0; }
|
|
||||||
|
|
||||||
/// Flush an output stream. Does nothing for non-writing streams.
|
|
||||||
virtual void flush() {}
|
|
||||||
|
|
||||||
/// Seek to an absolute position in this stream. Not all streams are
|
|
||||||
/// seekable.
|
|
||||||
virtual void seek(size_t pos) { assert(0); }
|
|
||||||
|
|
||||||
/// Get the current position in the stream. Non-seekable streams are
|
|
||||||
/// not required to keep track of this.
|
|
||||||
virtual size_t tell() const { assert(0); return 0; }
|
|
||||||
|
|
||||||
/// Return the total size of the stream. For streams hasSize is
|
|
||||||
/// false, size() should fail in some way, since it is an error to
|
|
||||||
/// call it in those cases.
|
|
||||||
virtual size_t size() const { assert(0); return 0; }
|
|
||||||
|
|
||||||
/// Returns true if the stream is empty. Required for readable
|
|
||||||
/// streams.
|
|
||||||
virtual bool eof() const { assert(0); return 0; }
|
|
||||||
|
|
||||||
/// Return a pointer to the entire stream. This function (and the
|
|
||||||
/// other getPtr() variants below) should only be implemented for
|
|
||||||
/// memory-based streams where using them would be an optimization.
|
|
||||||
virtual const void *getPtr() { assert(0); return NULL; }
|
|
||||||
|
|
||||||
/// Get a pointer to a memory region of 'size' bytes starting from
|
|
||||||
/// position 'pos'
|
|
||||||
virtual const void *getPtr(size_t pos, size_t size) { assert(0); return NULL; }
|
|
||||||
|
|
||||||
/// Get a pointer to a memory region of 'size' bytes from the
|
|
||||||
/// current position. Unlike the two other getPtr variants, this
|
|
||||||
/// will advance the position past the returned area.
|
|
||||||
virtual const void *getPtr(size_t size) { assert(0); return NULL; }
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef boost::shared_ptr<Stream> StreamPtr;
|
|
||||||
|
|
||||||
}} // namespaces
|
|
||||||
#endif
|
|
2
libs/mangle/stream/tests/.gitignore
vendored
2
libs/mangle/stream/tests/.gitignore
vendored
|
@ -1,2 +0,0 @@
|
||||||
*_test
|
|
||||||
test.file
|
|
|
@ -1,34 +0,0 @@
|
||||||
GCC=g++ -I../ -Wall -Werror
|
|
||||||
|
|
||||||
all: ogre_client_test audiere_client_test memory_server_test buffer_filter_test file_server_test slice_filter_test file_write_test iostream_test
|
|
||||||
|
|
||||||
I_OGRE=$(shell pkg-config --cflags OGRE)
|
|
||||||
L_OGRE=$(shell pkg-config --libs OGRE)
|
|
||||||
L_AUDIERE=-laudiere
|
|
||||||
|
|
||||||
ogre_client_test: ogre_client_test.cpp ../stream.hpp ../clients/ogre_datastream.hpp
|
|
||||||
$(GCC) $< -o $@ $(I_OGRE) $(L_OGRE)
|
|
||||||
|
|
||||||
audiere_client_test: audiere_client_test.cpp ../stream.hpp ../clients/audiere_file.hpp ../clients/audiere_file.cpp
|
|
||||||
$(GCC) $< -o $@ ../clients/audiere_file.cpp $(L_AUDIERE)
|
|
||||||
|
|
||||||
iostream_test: iostream_test.cpp ../clients/io_stream.cpp
|
|
||||||
$(GCC) $^ -o $@
|
|
||||||
|
|
||||||
file_server_test: file_server_test.cpp ../stream.hpp ../servers/file_stream.hpp ../servers/std_stream.hpp
|
|
||||||
$(GCC) $< -o $@
|
|
||||||
|
|
||||||
file_write_test: file_write_test.cpp ../stream.hpp ../servers/outfile_stream.hpp ../servers/std_ostream.hpp
|
|
||||||
$(GCC) $< -o $@
|
|
||||||
|
|
||||||
memory_server_test: memory_server_test.cpp ../stream.hpp ../servers/memory_stream.hpp
|
|
||||||
$(GCC) $< -o $@
|
|
||||||
|
|
||||||
buffer_filter_test: buffer_filter_test.cpp ../stream.hpp ../servers/memory_stream.hpp ../filters/buffer_stream.hpp
|
|
||||||
$(GCC) $< -o $@
|
|
||||||
|
|
||||||
slice_filter_test: slice_filter_test.cpp ../stream.hpp ../servers/memory_stream.hpp ../filters/slice_stream.hpp
|
|
||||||
$(GCC) $< -o $@
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm *_test
|
|
|
@ -1,34 +0,0 @@
|
||||||
#include "../servers/memory_stream.hpp"
|
|
||||||
#include "../clients/audiere_file.hpp"
|
|
||||||
#include <audiere.h>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
using namespace Mangle::Stream;
|
|
||||||
using namespace audiere;
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
char str[12];
|
|
||||||
memset(str, 0, 12);
|
|
||||||
StreamPtr inp(new MemoryStream("hello world", 11));
|
|
||||||
FilePtr p(new AudiereFile(inp));
|
|
||||||
cout << "pos=" << p->tell() << endl;
|
|
||||||
p->read(str, 2);
|
|
||||||
cout << "2 bytes: " << str << endl;
|
|
||||||
cout << "pos=" << p->tell() << endl;
|
|
||||||
p->seek(4, File::BEGIN);
|
|
||||||
cout << "pos=" << p->tell() << endl;
|
|
||||||
p->read(str, 3);
|
|
||||||
cout << "3 bytes: " << str << endl;
|
|
||||||
p->seek(-1, File::CURRENT);
|
|
||||||
cout << "pos=" << p->tell() << endl;
|
|
||||||
p->seek(-4, File::END);
|
|
||||||
cout << "pos=" << p->tell() << endl;
|
|
||||||
p->read(str, 4);
|
|
||||||
cout << "last 4 bytes: " << str << endl;
|
|
||||||
p->seek(0, File::BEGIN);
|
|
||||||
p->read(str, 11);
|
|
||||||
cout << "entire stream: " << str << endl;
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,41 +0,0 @@
|
||||||
#include <iostream>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "../filters/buffer_stream.hpp"
|
|
||||||
|
|
||||||
using namespace Mangle::Stream;
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
StreamPtr orig (new MemoryStream("hello world", 11));
|
|
||||||
StreamPtr inp (new BufferStream(orig));
|
|
||||||
|
|
||||||
cout << "Size: " << inp->size() << endl;
|
|
||||||
cout << "Pos: " << inp->tell() << "\nSeeking...\n";
|
|
||||||
inp->seek(3);
|
|
||||||
cout << "Pos: " << inp->tell() << endl;
|
|
||||||
char data[12];
|
|
||||||
memset(data, 0, 12);
|
|
||||||
cout << "Reading: " << inp->read(data, 4) << endl;
|
|
||||||
cout << "Four bytes: " << data << endl;
|
|
||||||
cout << "Eof: " << inp->eof() << endl;
|
|
||||||
cout << "Pos: " << inp->tell() << "\nSeeking again...\n";
|
|
||||||
inp->seek(33);
|
|
||||||
cout << "Pos: " << inp->tell() << endl;
|
|
||||||
cout << "Eof: " << inp->eof() << "\nSeek to 6\n";
|
|
||||||
inp->seek(6);
|
|
||||||
cout << "Eof: " << inp->eof() << endl;
|
|
||||||
cout << "Pos: " << inp->tell() << endl;
|
|
||||||
cout << "Over-reading: " << inp->read(data, 200) << endl;
|
|
||||||
cout << "Result: " << data << endl;
|
|
||||||
cout << "Eof: " << inp->eof() << endl;
|
|
||||||
cout << "Pos: " << inp->tell() << endl;
|
|
||||||
inp->seek(0);
|
|
||||||
cout << "Finally, reading the entire string: " << inp->read(data,11) << endl;
|
|
||||||
cout << "Result: " << data << endl;
|
|
||||||
cout << "Eof: " << inp->eof() << endl;
|
|
||||||
cout << "Pos: " << inp->tell() << endl;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
#include "../servers/file_stream.hpp"
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
using namespace Mangle::Stream;
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
StreamPtr inp(new FileStream("file_server_test.cpp"));
|
|
||||||
|
|
||||||
char buf[21];
|
|
||||||
buf[20] = 0;
|
|
||||||
cout << "pos=" << inp->tell() << " eof=" << inp->eof() << endl;
|
|
||||||
inp->read(buf, 20);
|
|
||||||
cout << "First 20 bytes: " << buf << endl;
|
|
||||||
cout << "pos=" << inp->tell() << " eof=" << inp->eof() << endl;
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,41 +0,0 @@
|
||||||
#include "../servers/outfile_stream.hpp"
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
using namespace Mangle::Stream;
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
void print(Stream &str)
|
|
||||||
{
|
|
||||||
cout << "size=" << str.size()
|
|
||||||
<< " pos=" << str.tell()
|
|
||||||
<< " eof=" << str.eof()
|
|
||||||
<< endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
cout << "\nCreating file\n";
|
|
||||||
OutFileStream out("test.file");
|
|
||||||
print(out);
|
|
||||||
out.write("hello",5);
|
|
||||||
print(out);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
cout << "\nAppending to file\n";
|
|
||||||
OutFileStream out("test.file", true);
|
|
||||||
print(out);
|
|
||||||
out.write(" again\n",7);
|
|
||||||
print(out);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
cout << "\nOverwriting file\n";
|
|
||||||
OutFileStream out("test.file");
|
|
||||||
print(out);
|
|
||||||
out.write("overwrite!\n",11);
|
|
||||||
print(out);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,176 +0,0 @@
|
||||||
#include <iostream>
|
|
||||||
#include "../clients/io_stream.hpp"
|
|
||||||
#include "../servers/memory_stream.hpp"
|
|
||||||
|
|
||||||
using namespace Mangle::Stream;
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
void test1()
|
|
||||||
{
|
|
||||||
cout << "Testing ASCII reading from memory:\n";
|
|
||||||
StreamPtr input(new MemoryStream("hello you world you", 19));
|
|
||||||
MangleIStream inp(input);
|
|
||||||
|
|
||||||
string str;
|
|
||||||
while(!inp.eof())
|
|
||||||
{
|
|
||||||
inp >> str;
|
|
||||||
cout << "Got: " << str << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Dummy : public Stream
|
|
||||||
{
|
|
||||||
int count;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
Dummy() : count(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t read(void *ptr, size_t num)
|
|
||||||
{
|
|
||||||
char *p = (char*)ptr;
|
|
||||||
char *start = p;
|
|
||||||
for(; (count < 2560) && (p-start < (int)num); count++)
|
|
||||||
{
|
|
||||||
*p = count / 10;
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
return p-start;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool eof() const { return count == 2560; }
|
|
||||||
};
|
|
||||||
|
|
||||||
void test2()
|
|
||||||
{
|
|
||||||
cout << "\nTesting binary reading from non-memory:\n";
|
|
||||||
|
|
||||||
StreamPtr input(new Dummy);
|
|
||||||
MangleIStream inp(input);
|
|
||||||
|
|
||||||
int x = 0;
|
|
||||||
while(!inp.eof())
|
|
||||||
{
|
|
||||||
unsigned char buf[5];
|
|
||||||
inp.read((char*)buf,5);
|
|
||||||
|
|
||||||
// istream doesn't set eof() until we read _beyond_ the end of
|
|
||||||
// the stream, so we need an extra check.
|
|
||||||
if(inp.gcount() == 0) break;
|
|
||||||
|
|
||||||
/*
|
|
||||||
for(int i=0;i<5;i++)
|
|
||||||
cout << (int)buf[i] << " ";
|
|
||||||
cout << endl;
|
|
||||||
*/
|
|
||||||
|
|
||||||
assert(buf[4] == buf[0]);
|
|
||||||
assert(buf[0] == x/2);
|
|
||||||
x++;
|
|
||||||
}
|
|
||||||
cout << " Done\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Dummy2 : Stream
|
|
||||||
{
|
|
||||||
Dummy2()
|
|
||||||
{
|
|
||||||
isWritable = true;
|
|
||||||
isReadable = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t write(const void *ptr, size_t num)
|
|
||||||
{
|
|
||||||
const char *p = (const char*)ptr;
|
|
||||||
cout << " Got: ";
|
|
||||||
for(unsigned i=0;i<num;i++)
|
|
||||||
cout << *(p++) << " ";
|
|
||||||
cout << endl;
|
|
||||||
return num;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void test3()
|
|
||||||
{
|
|
||||||
cout << "\nWriting to dummy stream:\n";
|
|
||||||
|
|
||||||
cout << " Pure dummy test:\n";
|
|
||||||
StreamPtr output(new Dummy2);
|
|
||||||
output->write("testing", 7);
|
|
||||||
|
|
||||||
cout << " Running through MangleOStream:\n";
|
|
||||||
MangleOStream out(output);
|
|
||||||
out << "hello";
|
|
||||||
out << " - are you ok?";
|
|
||||||
cout << " Flushing:\n";
|
|
||||||
out.flush();
|
|
||||||
|
|
||||||
cout << " Writing a hell of a lot of characters:\n";
|
|
||||||
for(int i=0; i<127; i++)
|
|
||||||
out << "xxxxxxxx"; // 127 * 8 = 1016
|
|
||||||
out << "fffffff"; // +7 = 1023
|
|
||||||
cout << " Just one more:\n";
|
|
||||||
out << "y";
|
|
||||||
cout << " And oooone more:\n";
|
|
||||||
out << "z";
|
|
||||||
|
|
||||||
cout << " Flushing again:\n";
|
|
||||||
out.flush();
|
|
||||||
cout << " Writing some more and exiting:\n";
|
|
||||||
out << "blah bleh blob";
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Dummy3 : Stream
|
|
||||||
{
|
|
||||||
int pos;
|
|
||||||
|
|
||||||
Dummy3() : pos(0)
|
|
||||||
{
|
|
||||||
hasPosition = true;
|
|
||||||
isSeekable = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t read(void*, size_t num)
|
|
||||||
{
|
|
||||||
cout << " Reading " << num << " bytes from " << pos << endl;
|
|
||||||
pos += num;
|
|
||||||
return num;
|
|
||||||
}
|
|
||||||
|
|
||||||
void seek(size_t npos) { pos = npos; }
|
|
||||||
size_t tell() const { return pos; }
|
|
||||||
};
|
|
||||||
|
|
||||||
void test4()
|
|
||||||
{
|
|
||||||
cout << "\nTesting seeking;\n";
|
|
||||||
StreamPtr input(new Dummy3);
|
|
||||||
|
|
||||||
cout << " Direct reading:\n";
|
|
||||||
input->read(0,10);
|
|
||||||
input->read(0,5);
|
|
||||||
|
|
||||||
MangleIStream inp(input);
|
|
||||||
|
|
||||||
cout << " Reading from istream:\n";
|
|
||||||
char buf[20];
|
|
||||||
inp.read(buf, 20);
|
|
||||||
inp.read(buf, 20);
|
|
||||||
inp.read(buf, 20);
|
|
||||||
|
|
||||||
cout << " Seeking to 30 and reading again:\n";
|
|
||||||
inp.seekg(30);
|
|
||||||
inp.read(buf, 20);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
test1();
|
|
||||||
test2();
|
|
||||||
test3();
|
|
||||||
test4();
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,42 +0,0 @@
|
||||||
#include <iostream>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "../servers/memory_stream.hpp"
|
|
||||||
|
|
||||||
using namespace Mangle::Stream;
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
Stream* inp = new MemoryStream("hello world\0", 12);
|
|
||||||
|
|
||||||
cout << "Size: " << inp->size() << endl;
|
|
||||||
cout << "Pos: " << inp->tell() << "\nSeeking...\n";
|
|
||||||
inp->seek(3);
|
|
||||||
cout << "Pos: " << inp->tell() << endl;
|
|
||||||
char data[12];
|
|
||||||
memset(data, 0, 12);
|
|
||||||
cout << "Reading: " << inp->read(data, 4) << endl;
|
|
||||||
cout << "Four bytes: " << data << endl;
|
|
||||||
cout << "Eof: " << inp->eof() << endl;
|
|
||||||
cout << "Pos: " << inp->tell() << "\nSeeking again...\n";
|
|
||||||
inp->seek(33);
|
|
||||||
cout << "Pos: " << inp->tell() << endl;
|
|
||||||
cout << "Eof: " << inp->eof() << "\nSeek to 6\n";
|
|
||||||
inp->seek(6);
|
|
||||||
cout << "Eof: " << inp->eof() << endl;
|
|
||||||
cout << "Pos: " << inp->tell() << endl;
|
|
||||||
cout << "Over-reading: " << inp->read(data, 200) << endl;
|
|
||||||
cout << "Result: " << data << endl;
|
|
||||||
cout << "Eof: " << inp->eof() << endl;
|
|
||||||
cout << "Pos: " << inp->tell() << endl;
|
|
||||||
inp->seek(0);
|
|
||||||
cout << "Finally, reading the entire string: " << inp->read(data,11) << endl;
|
|
||||||
cout << "Result: " << data << endl;
|
|
||||||
cout << "Eof: " << inp->eof() << endl;
|
|
||||||
cout << "Pos: " << inp->tell() << endl;
|
|
||||||
|
|
||||||
cout << "Entire stream from pointer: " << (char*)inp->getPtr() << endl;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
#include "../servers/memory_stream.hpp"
|
|
||||||
#include "../clients/ogre_datastream.hpp"
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
using namespace Mangle::Stream;
|
|
||||||
using namespace Ogre;
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
StreamPtr inp(new MemoryStream("hello world", 11));
|
|
||||||
DataStreamPtr p(new Mangle2OgreStream("hello", inp));
|
|
||||||
cout << "Name: " << p->getName() << endl;
|
|
||||||
cout << "As string: " << p->getAsString() << endl;
|
|
||||||
cout << "pos=" << p->tell() << " eof=" << p->eof() << endl;
|
|
||||||
p->seek(0);
|
|
||||||
cout << "pos=" << p->tell() << " eof=" << p->eof() << endl;
|
|
||||||
p->skip(5);
|
|
||||||
p->skip(-2);
|
|
||||||
cout << "pos=" << p->tell() << " eof=" << p->eof() << endl;
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
pos=0
|
|
||||||
2 bytes: he
|
|
||||||
pos=2
|
|
||||||
pos=4
|
|
||||||
3 bytes: o w
|
|
||||||
pos=6
|
|
||||||
pos=7
|
|
||||||
last 4 bytes: orld
|
|
||||||
entire stream: hello world
|
|
|
@ -1,22 +0,0 @@
|
||||||
Size: 11
|
|
||||||
Pos: 0
|
|
||||||
Seeking...
|
|
||||||
Pos: 3
|
|
||||||
Reading: 4
|
|
||||||
Four bytes: lo w
|
|
||||||
Eof: 0
|
|
||||||
Pos: 7
|
|
||||||
Seeking again...
|
|
||||||
Pos: 11
|
|
||||||
Eof: 1
|
|
||||||
Seek to 6
|
|
||||||
Eof: 0
|
|
||||||
Pos: 6
|
|
||||||
Over-reading: 5
|
|
||||||
Result: world
|
|
||||||
Eof: 1
|
|
||||||
Pos: 11
|
|
||||||
Finally, reading the entire string: 11
|
|
||||||
Result: hello world
|
|
||||||
Eof: 1
|
|
||||||
Pos: 11
|
|
|
@ -1,3 +0,0 @@
|
||||||
pos=0 eof=0
|
|
||||||
First 20 bytes: #include "../servers
|
|
||||||
pos=20 eof=0
|
|
|
@ -1,12 +0,0 @@
|
||||||
|
|
||||||
Creating file
|
|
||||||
size=0 pos=0 eof=0
|
|
||||||
size=5 pos=5 eof=0
|
|
||||||
|
|
||||||
Appending to file
|
|
||||||
size=5 pos=5 eof=0
|
|
||||||
size=12 pos=12 eof=0
|
|
||||||
|
|
||||||
Overwriting file
|
|
||||||
size=0 pos=0 eof=0
|
|
||||||
size=11 pos=11 eof=0
|
|
|
@ -1,32 +0,0 @@
|
||||||
Testing ASCII reading from memory:
|
|
||||||
Got: hello
|
|
||||||
Got: you
|
|
||||||
Got: world
|
|
||||||
Got: you
|
|
||||||
|
|
||||||
Testing binary reading from non-memory:
|
|
||||||
Done
|
|
||||||
|
|
||||||
Writing to dummy stream:
|
|
||||||
Pure dummy test:
|
|
||||||
Got: t e s t i n g
|
|
||||||
Running through MangleOStream:
|
|
||||||
Flushing:
|
|
||||||
Got: h e l l o - a r e y o u o k ?
|
|
||||||
Writing a hell of a lot of characters:
|
|
||||||
Just one more:
|
|
||||||
And oooone more:
|
|
||||||
Got: x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x f f f f f f f y
|
|
||||||
Flushing again:
|
|
||||||
Got: z
|
|
||||||
Writing some more and exiting:
|
|
||||||
Got: b l a h b l e h b l o b
|
|
||||||
|
|
||||||
Testing seeking;
|
|
||||||
Direct reading:
|
|
||||||
Reading 10 bytes from 0
|
|
||||||
Reading 5 bytes from 10
|
|
||||||
Reading from istream:
|
|
||||||
Reading 1024 bytes from 15
|
|
||||||
Seeking to 30 and reading again:
|
|
||||||
Reading 1024 bytes from 30
|
|
|
@ -1,23 +0,0 @@
|
||||||
Size: 12
|
|
||||||
Pos: 0
|
|
||||||
Seeking...
|
|
||||||
Pos: 3
|
|
||||||
Reading: 4
|
|
||||||
Four bytes: lo w
|
|
||||||
Eof: 0
|
|
||||||
Pos: 7
|
|
||||||
Seeking again...
|
|
||||||
Pos: 12
|
|
||||||
Eof: 1
|
|
||||||
Seek to 6
|
|
||||||
Eof: 0
|
|
||||||
Pos: 6
|
|
||||||
Over-reading: 6
|
|
||||||
Result: world
|
|
||||||
Eof: 1
|
|
||||||
Pos: 12
|
|
||||||
Finally, reading the entire string: 11
|
|
||||||
Result: hello world
|
|
||||||
Eof: 0
|
|
||||||
Pos: 11
|
|
||||||
Entire stream from pointer: hello world
|
|
|
@ -1,5 +0,0 @@
|
||||||
Name: hello
|
|
||||||
As string: hello world
|
|
||||||
pos=11 eof=1
|
|
||||||
pos=0 eof=0
|
|
||||||
pos=3 eof=0
|
|
|
@ -1,36 +0,0 @@
|
||||||
|
|
||||||
Slice 1:
|
|
||||||
--------
|
|
||||||
Size: 6
|
|
||||||
Pos: 0
|
|
||||||
Seeking...
|
|
||||||
Reading 6 bytes
|
|
||||||
Result: hello
|
|
||||||
Pos: 6
|
|
||||||
Eof: 1
|
|
||||||
Seeking:
|
|
||||||
Pos: 2
|
|
||||||
Eof: 0
|
|
||||||
Reading 4 bytes
|
|
||||||
Result: llo
|
|
||||||
Pos: 6
|
|
||||||
Eof: 1
|
|
||||||
Entire stream as pointer: hello
|
|
||||||
|
|
||||||
Slice 2:
|
|
||||||
--------
|
|
||||||
Size: 6
|
|
||||||
Pos: 0
|
|
||||||
Seeking...
|
|
||||||
Reading 6 bytes
|
|
||||||
Result: world
|
|
||||||
Pos: 6
|
|
||||||
Eof: 1
|
|
||||||
Seeking:
|
|
||||||
Pos: 2
|
|
||||||
Eof: 0
|
|
||||||
Reading 4 bytes
|
|
||||||
Result: rld
|
|
||||||
Pos: 6
|
|
||||||
Eof: 1
|
|
||||||
Entire stream as pointer: world
|
|
|
@ -1,42 +0,0 @@
|
||||||
#include <iostream>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "../filters/slice_stream.hpp"
|
|
||||||
#include "../servers/memory_stream.hpp"
|
|
||||||
|
|
||||||
using namespace Mangle::Stream;
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
void test(StreamPtr inp)
|
|
||||||
{
|
|
||||||
cout << "Size: " << inp->size() << endl;
|
|
||||||
cout << "Pos: " << inp->tell() << "\nSeeking...\n";
|
|
||||||
char data[6];
|
|
||||||
memset(data, 0, 6);
|
|
||||||
cout << "Reading " << inp->read(data, 6) << " bytes\n";
|
|
||||||
cout << "Result: " << data << endl;
|
|
||||||
cout << "Pos: " << inp->tell() << endl;
|
|
||||||
cout << "Eof: " << inp->eof() << endl;
|
|
||||||
inp->seek(2);
|
|
||||||
cout << "Seeking:\nPos: " << inp->tell() << endl;
|
|
||||||
cout << "Eof: " << inp->eof() << endl;
|
|
||||||
cout << "Reading " << inp->read(data, 6) << " bytes\n";
|
|
||||||
cout << "Result: " << data << endl;
|
|
||||||
cout << "Pos: " << inp->tell() << endl;
|
|
||||||
cout << "Eof: " << inp->eof() << endl;
|
|
||||||
cout << "Entire stream as pointer: " << (char*)inp->getPtr() << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
StreamPtr orig (new MemoryStream("hello\0world\0", 12));
|
|
||||||
StreamPtr slice1 (new SliceStream(orig,0,6));
|
|
||||||
StreamPtr slice2 (new SliceStream(orig,6,6));
|
|
||||||
|
|
||||||
cout << "\nSlice 1:\n--------\n";
|
|
||||||
test(slice1);
|
|
||||||
cout << "\nSlice 2:\n--------\n";
|
|
||||||
test(slice2);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
make || exit
|
|
||||||
|
|
||||||
mkdir -p output
|
|
||||||
|
|
||||||
PROGS=*_test
|
|
||||||
|
|
||||||
for a in $PROGS; do
|
|
||||||
if [ -f "output/$a.out" ]; then
|
|
||||||
echo "Running $a:"
|
|
||||||
./$a | diff output/$a.out -
|
|
||||||
else
|
|
||||||
echo "Creating $a.out"
|
|
||||||
./$a > "output/$a.out"
|
|
||||||
git add "output/$a.out"
|
|
||||||
fi
|
|
||||||
done
|
|
|
@ -1,85 +0,0 @@
|
||||||
#include "ogre_archive.hpp"
|
|
||||||
|
|
||||||
#include "../../stream/clients/ogre_datastream.hpp"
|
|
||||||
|
|
||||||
using namespace Mangle::VFS;
|
|
||||||
using namespace Mangle::Stream;
|
|
||||||
|
|
||||||
Ogre::DataStreamPtr MangleArchive::open(const Ogre::String& filename) const
|
|
||||||
{
|
|
||||||
return Ogre::DataStreamPtr(new Mangle2OgreStream
|
|
||||||
(filename, vfs->open(filename)));
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
assert(vfs->hasList);
|
|
||||||
FileInfoListPtr 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)
|
|
||||||
{
|
|
||||||
assert(vfs->hasList);
|
|
||||||
FileInfoListPtr 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);
|
|
||||||
FileInfoListPtr 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);
|
|
||||||
FileInfoListPtr lst = vfs->find(pattern, recursive, dirs);
|
|
||||||
Ogre::FileInfoList *res = new Ogre::FileInfoList;
|
|
||||||
|
|
||||||
fill(*res, *lst);
|
|
||||||
|
|
||||||
return Ogre::FileInfoListPtr(res);
|
|
||||||
}
|
|
|
@ -1,59 +0,0 @@
|
||||||
#ifndef MANGLE_VFS_OGRECLIENT_H
|
|
||||||
#define MANGLE_VFS_OGRECLIENT_H
|
|
||||||
|
|
||||||
#include <OgreArchive.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include "../vfs.hpp"
|
|
||||||
|
|
||||||
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, and has been
|
|
||||||
extended for OGRE 1.7. You might have to make your own
|
|
||||||
modifications if you're working with newer (or older) versions.
|
|
||||||
*/
|
|
||||||
class MangleArchive : public Ogre::Archive
|
|
||||||
{
|
|
||||||
VFSPtr vfs;
|
|
||||||
|
|
||||||
public:
|
|
||||||
MangleArchive(VFSPtr _vfs, const std::string &name,
|
|
||||||
const std::string &archType = "Mangle")
|
|
||||||
: Ogre::Archive(name, archType)
|
|
||||||
, vfs(_vfs)
|
|
||||||
{}
|
|
||||||
|
|
||||||
bool isCaseSensitive() const { return vfs->isCaseSensitive; }
|
|
||||||
|
|
||||||
// These do nothing. You have to load / unload the archive in the
|
|
||||||
// constructor/destructor.
|
|
||||||
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; }
|
|
||||||
|
|
||||||
// With both these we support both OGRE 1.6 and 1.7
|
|
||||||
Ogre::DataStreamPtr open(const Ogre::String& filename) const;
|
|
||||||
Ogre::DataStreamPtr open(const Ogre::String& filename, bool readOnly) const
|
|
||||||
{ return open(filename); }
|
|
||||||
|
|
||||||
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
|
|
|
@ -1,61 +0,0 @@
|
||||||
#include "ogre_vfs.hpp"
|
|
||||||
#include "../../stream/servers/ogre_datastream.hpp"
|
|
||||||
|
|
||||||
using namespace Mangle::VFS;
|
|
||||||
using namespace Mangle::Stream;
|
|
||||||
|
|
||||||
OgreVFS::OgreVFS(const std::string &_group)
|
|
||||||
: group(_group)
|
|
||||||
{
|
|
||||||
hasList = true;
|
|
||||||
hasFind = true;
|
|
||||||
isCaseSensitive = true;
|
|
||||||
|
|
||||||
// Get the group manager once
|
|
||||||
gm = Ogre::ResourceGroupManager::getSingletonPtr();
|
|
||||||
|
|
||||||
// Use the default group if none was specified
|
|
||||||
if(group.empty())
|
|
||||||
group = gm->getWorldResourceGroupName();
|
|
||||||
}
|
|
||||||
|
|
||||||
StreamPtr OgreVFS::open(const std::string &name)
|
|
||||||
{
|
|
||||||
Ogre::DataStreamPtr data = gm->openResource(name, group);
|
|
||||||
return StreamPtr(new OgreStream(data));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void fill(FileInfoList &out, Ogre::FileInfoList &in, bool dirs)
|
|
||||||
{
|
|
||||||
int size = in.size();
|
|
||||||
out.resize(size);
|
|
||||||
|
|
||||||
for(int i=0; i<size; i++)
|
|
||||||
{
|
|
||||||
out[i].name = in[i].filename;
|
|
||||||
out[i].basename = in[i].basename;
|
|
||||||
out[i].size = in[i].uncompressedSize;
|
|
||||||
out[i].isDir = dirs;
|
|
||||||
out[i].time = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FileInfoListPtr OgreVFS::list(const std::string& dir,
|
|
||||||
bool recurse,
|
|
||||||
bool dirs) const
|
|
||||||
{
|
|
||||||
Ogre::FileInfoListPtr olist = gm->listResourceFileInfo(group, dirs);
|
|
||||||
FileInfoListPtr res(new FileInfoList);
|
|
||||||
fill(*res, *olist, dirs);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
FileInfoListPtr OgreVFS::find(const std::string& pattern,
|
|
||||||
bool recursive,
|
|
||||||
bool dirs) const
|
|
||||||
{
|
|
||||||
Ogre::FileInfoListPtr olist = gm->findResourceFileInfo(group, pattern, dirs);
|
|
||||||
FileInfoListPtr res(new FileInfoList);
|
|
||||||
fill(*res, *olist, dirs);
|
|
||||||
return res;
|
|
||||||
}
|
|
|
@ -1,70 +0,0 @@
|
||||||
#ifndef MANGLE_VFS_OGRESERVER_H
|
|
||||||
#define MANGLE_VFS_OGRESERVER_H
|
|
||||||
|
|
||||||
#include "../vfs.hpp"
|
|
||||||
#include <OgreResourceGroupManager.h>
|
|
||||||
|
|
||||||
namespace Mangle {
|
|
||||||
namespace VFS {
|
|
||||||
|
|
||||||
/** @brief An interface into the OGRE VFS system.
|
|
||||||
|
|
||||||
This class does NOT wrap a single Ogre::Archive, but rather an
|
|
||||||
entire resource group in Ogre. You can use this class to tap into
|
|
||||||
all paths, Zip files, custom archives on so on that have been
|
|
||||||
inserted into Ogre as resource locations.
|
|
||||||
|
|
||||||
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 OgreVFS : public VFS
|
|
||||||
{
|
|
||||||
std::string group;
|
|
||||||
Ogre::ResourceGroupManager *gm;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/** @brief Constructor
|
|
||||||
|
|
||||||
OGRE must be initialized (ie. you must have created an
|
|
||||||
Ogre::Root object somewhere) before calling this.
|
|
||||||
|
|
||||||
@param group Optional resource group name. If none is given,
|
|
||||||
OGRE's default (or 'World') resource group is used.
|
|
||||||
*/
|
|
||||||
OgreVFS(const std::string &_group = "");
|
|
||||||
|
|
||||||
/// Open a new data stream. Deleting the object should be enough to
|
|
||||||
/// close it.
|
|
||||||
virtual Stream::StreamPtr open(const std::string &name);
|
|
||||||
|
|
||||||
/// Check for the existence of a file
|
|
||||||
virtual bool isFile(const std::string &name) const
|
|
||||||
{ return gm->resourceExists(group, name); }
|
|
||||||
|
|
||||||
/// This doesn't work, always returns false.
|
|
||||||
virtual bool isDir(const std::string &name) const
|
|
||||||
{ return false; }
|
|
||||||
|
|
||||||
/// This doesn't work.
|
|
||||||
virtual FileInfoPtr stat(const std::string &name) const
|
|
||||||
{ return FileInfoPtr(); }
|
|
||||||
|
|
||||||
/// 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. OGRE note: The
|
|
||||||
/// ogre resource systemd does not support recursive listing of
|
|
||||||
/// files. We might make a separate filter for this later.
|
|
||||||
virtual FileInfoListPtr list(const std::string& dir = "",
|
|
||||||
bool recurse=true,
|
|
||||||
bool dirs=false) const;
|
|
||||||
|
|
||||||
/// Find files after a given pattern. Wildcards (*) are
|
|
||||||
/// supported.
|
|
||||||
virtual FileInfoListPtr find(const std::string& pattern,
|
|
||||||
bool recursive=true,
|
|
||||||
bool dirs=false) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
}} // namespaces
|
|
||||||
#endif
|
|
|
@ -1,71 +0,0 @@
|
||||||
#ifndef MANGLE_VFS_PHYSFS_SERVER_H
|
|
||||||
#define MANGLE_VFS_PHYSFS_SERVER_H
|
|
||||||
|
|
||||||
#include "../vfs.hpp"
|
|
||||||
#include "../../stream/servers/phys_stream.hpp"
|
|
||||||
|
|
||||||
#include <physfs.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
namespace Mangle {
|
|
||||||
namespace VFS {
|
|
||||||
|
|
||||||
/** @brief An interface into the PhysFS virtual file system library
|
|
||||||
|
|
||||||
You have to set up PhysFS on your own before using this class.
|
|
||||||
*/
|
|
||||||
class PhysVFS : public VFS
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PhysVFS()
|
|
||||||
{
|
|
||||||
hasList = true;
|
|
||||||
hasFind = false;
|
|
||||||
isCaseSensitive = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Open a new data stream. Deleting the object should be enough to
|
|
||||||
/// close it.
|
|
||||||
virtual Stream::StreamPtr open(const std::string &name)
|
|
||||||
{ return Stream::StreamPtr(new Stream::PhysFile(PHYSFS_openRead(name.c_str()))); }
|
|
||||||
|
|
||||||
/// Check for the existence of a file
|
|
||||||
virtual bool isFile(const std::string &name) const
|
|
||||||
{ return PHYSFS_exists(name.c_str()); }
|
|
||||||
|
|
||||||
/// Checks for a directory
|
|
||||||
virtual bool isDir(const std::string &name) const
|
|
||||||
{ return PHYSFS_isDirectory(name.c_str()); }
|
|
||||||
|
|
||||||
/// This doesn't work
|
|
||||||
virtual FileInfoPtr stat(const std::string &name) const
|
|
||||||
{ assert(0); return FileInfoPtr(); }
|
|
||||||
|
|
||||||
virtual FileInfoListPtr list(const std::string& dir = "",
|
|
||||||
bool recurse=true,
|
|
||||||
bool dirs=false) const
|
|
||||||
{
|
|
||||||
char **files = PHYSFS_enumerateFiles(dir.c_str());
|
|
||||||
FileInfoListPtr lst(new FileInfoList);
|
|
||||||
|
|
||||||
// Add all teh files
|
|
||||||
int i = 0;
|
|
||||||
while(files[i] != NULL)
|
|
||||||
{
|
|
||||||
FileInfo fi;
|
|
||||||
fi.name = files[i];
|
|
||||||
fi.isDir = false;
|
|
||||||
|
|
||||||
lst->push_back(fi);
|
|
||||||
}
|
|
||||||
return lst;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual FileInfoListPtr find(const std::string& pattern,
|
|
||||||
bool recursive=true,
|
|
||||||
bool dirs=false) const
|
|
||||||
{ assert(0); }
|
|
||||||
};
|
|
||||||
|
|
||||||
}} // namespaces
|
|
||||||
#endif
|
|
1
libs/mangle/vfs/tests/.gitignore
vendored
1
libs/mangle/vfs/tests/.gitignore
vendored
|
@ -1 +0,0 @@
|
||||||
*_test
|
|
|
@ -1,25 +0,0 @@
|
||||||
GCC=g++ -I../ -Wall
|
|
||||||
|
|
||||||
all: dummy_test ogre_client_test ogre_resource_test ogre_server_test physfs_server_test
|
|
||||||
|
|
||||||
I_OGRE=$(shell pkg-config --cflags OGRE)
|
|
||||||
L_OGRE=$(shell pkg-config --libs OGRE)
|
|
||||||
L_PHYSFS=-lphysfs
|
|
||||||
|
|
||||||
ogre_client_test: ogre_client_test.cpp dummy_vfs.cpp ../vfs.hpp ../clients/ogre_archive.hpp ../clients/ogre_archive.cpp
|
|
||||||
$(GCC) $< ../clients/ogre_archive.cpp -o $@ $(I_OGRE) $(L_OGRE)
|
|
||||||
|
|
||||||
ogre_resource_test: ogre_resource_test.cpp
|
|
||||||
$(GCC) $< -o $@ $(I_OGRE) $(L_OGRE)
|
|
||||||
|
|
||||||
ogre_server_test: ogre_server_test.cpp ../vfs.hpp ../servers/ogre_vfs.hpp ../servers/ogre_vfs.cpp
|
|
||||||
$(GCC) $< -o $@ $(I_OGRE) $(L_OGRE) ../servers/ogre_vfs.cpp
|
|
||||||
|
|
||||||
physfs_server_test: physfs_server_test.cpp ../vfs.hpp ../servers/physfs_vfs.hpp
|
|
||||||
$(GCC) $< -o $@ $(L_PHYSFS)
|
|
||||||
|
|
||||||
dummy_test: dummy_test.cpp dummy_vfs.cpp ../vfs.hpp
|
|
||||||
$(GCC) $< -o $@
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm *_test
|
|
|
@ -1,42 +0,0 @@
|
||||||
#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(FileInfoPtr inf) { print(*inf); }
|
|
||||||
|
|
||||||
void print(FileInfoList &lst)
|
|
||||||
{
|
|
||||||
for(unsigned i=0; i<lst.size(); i++)
|
|
||||||
print(lst[i]);
|
|
||||||
}
|
|
||||||
void print(FileInfoListPtr lst) { print(*lst); }
|
|
||||||
|
|
||||||
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"));
|
|
||||||
|
|
||||||
StreamPtr inp = vfs.open("file1");
|
|
||||||
cout << "filesize: " << inp->size() << endl;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,117 +0,0 @@
|
||||||
// This file is shared between several test programs
|
|
||||||
#include "vfs.hpp"
|
|
||||||
#include <assert.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "../../stream/servers/memory_stream.hpp"
|
|
||||||
|
|
||||||
using namespace Mangle::VFS;
|
|
||||||
using namespace Mangle::Stream;
|
|
||||||
|
|
||||||
class DummyVFS : public VFS
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
DummyVFS()
|
|
||||||
{
|
|
||||||
hasFind = false;
|
|
||||||
hasList = true;
|
|
||||||
isCaseSensitive = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We only support opening 'file1' at the moment.
|
|
||||||
StreamPtr open(const std::string &name)
|
|
||||||
{
|
|
||||||
assert(name == "file1");
|
|
||||||
return StreamPtr(new MemoryStream("hello world", 11));
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
FileInfoPtr stat(const std::string &name) const
|
|
||||||
{
|
|
||||||
FileInfoPtr fi(new FileInfo);
|
|
||||||
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 FileInfoListPtr list(const std::string& dir = "",
|
|
||||||
bool recurse=true,
|
|
||||||
bool dirs=false) const
|
|
||||||
{
|
|
||||||
assert(dir == "");
|
|
||||||
|
|
||||||
FileInfoListPtr fl(new FileInfoList);
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
FileInfoListPtr find(const std::string& pattern,
|
|
||||||
bool recursive=true,
|
|
||||||
bool dirs=false) const
|
|
||||||
{ assert(0); }
|
|
||||||
};
|
|
|
@ -1,39 +0,0 @@
|
||||||
#include "dummy_vfs.cpp"
|
|
||||||
#include "../clients/ogre_archive.hpp"
|
|
||||||
#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()
|
|
||||||
{
|
|
||||||
VFSPtr 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;
|
|
||||||
}
|
|
|
@ -1,61 +0,0 @@
|
||||||
#include <iostream>
|
|
||||||
#include <OgreRoot.h>
|
|
||||||
#include <OgreResourceGroupManager.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
This isn't really a test of our implementation, but a test of using
|
|
||||||
the Ogre resource system to find files. If the Ogre interface
|
|
||||||
changes and you have to change this test, you will have to change
|
|
||||||
the servers/ogre_vfs.cpp implementation equivalently.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace Ogre;
|
|
||||||
|
|
||||||
ResourceGroupManager *gm;
|
|
||||||
String group;
|
|
||||||
|
|
||||||
void find(const std::string &fileName)
|
|
||||||
{
|
|
||||||
cout << "\nFile: " << fileName << endl;
|
|
||||||
|
|
||||||
if(!gm->resourceExists(group, fileName))
|
|
||||||
{
|
|
||||||
cout << "Does not exist\n";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DataStreamPtr data = gm->openResource(fileName, group);
|
|
||||||
|
|
||||||
cout << "Size: " << data->size() << endl;
|
|
||||||
cout << "First line: " << data->getLine() << "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
// Disable logging
|
|
||||||
new LogManager;
|
|
||||||
Log *log = LogManager::getSingleton().createLog("");
|
|
||||||
log->setDebugOutputEnabled(false);
|
|
||||||
|
|
||||||
// Set up Ogre
|
|
||||||
Root root("","","");
|
|
||||||
|
|
||||||
root.addResourceLocation("./", "FileSystem", "General");
|
|
||||||
|
|
||||||
gm = ResourceGroupManager::getSingletonPtr();
|
|
||||||
group = gm->getWorldResourceGroupName();
|
|
||||||
|
|
||||||
find("Makefile");
|
|
||||||
find("ogre_resource_test.cpp");
|
|
||||||
find("bleh");
|
|
||||||
|
|
||||||
cout << "\nAll source files:\n";
|
|
||||||
FileInfoListPtr list = gm->findResourceFileInfo(group, "*.cpp");
|
|
||||||
FileInfoList::iterator it, end;
|
|
||||||
it = list->begin();
|
|
||||||
end = list->end();
|
|
||||||
for(; it != end; it++)
|
|
||||||
cout << " " << it->filename << endl;
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
#include "../servers/ogre_vfs.hpp"
|
|
||||||
|
|
||||||
#include <Ogre.h>
|
|
||||||
|
|
||||||
#include "server_common.cpp"
|
|
||||||
|
|
||||||
Ogre::Root *root;
|
|
||||||
|
|
||||||
void setupOgre()
|
|
||||||
{
|
|
||||||
using namespace Ogre;
|
|
||||||
|
|
||||||
// Disable logging
|
|
||||||
new LogManager;
|
|
||||||
Log *log = LogManager::getSingleton().createLog("");
|
|
||||||
log->setDebugOutputEnabled(false);
|
|
||||||
|
|
||||||
// Set up Root
|
|
||||||
root = new Root("","","");
|
|
||||||
|
|
||||||
// Add a zip file and the current directory
|
|
||||||
root->addResourceLocation("test.zip", "Zip", "General");
|
|
||||||
root->addResourceLocation("./", "FileSystem", "General");
|
|
||||||
}
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
// Set up the engine
|
|
||||||
setupOgre();
|
|
||||||
|
|
||||||
// This is our entry point into the resource file system
|
|
||||||
OgreVFS vfs("General");
|
|
||||||
|
|
||||||
// Run the test
|
|
||||||
testAll(vfs);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
Listing all files:
|
|
||||||
name: file1
|
|
||||||
basename: file1
|
|
||||||
isDir: 0
|
|
||||||
size: 1
|
|
||||||
time: 0
|
|
||||||
name: dir/file2
|
|
||||||
basename: file2
|
|
||||||
isDir: 0
|
|
||||||
size: 2
|
|
||||||
time: 0
|
|
||||||
|
|
||||||
Stat for single files:
|
|
||||||
name: file1
|
|
||||||
basename: file1
|
|
||||||
isDir: 0
|
|
||||||
size: 1
|
|
||||||
time: 0
|
|
||||||
|
|
||||||
name: dir/file2
|
|
||||||
basename: file2
|
|
||||||
isDir: 0
|
|
||||||
size: 2
|
|
||||||
time: 0
|
|
||||||
|
|
||||||
name: dir
|
|
||||||
basename: dir
|
|
||||||
isDir: 1
|
|
||||||
size: 0
|
|
||||||
time: 0
|
|
||||||
filesize: 11
|
|
|
@ -1,12 +0,0 @@
|
||||||
Case: 1
|
|
||||||
Name: dummy
|
|
||||||
Type: Mangle
|
|
||||||
All files:
|
|
||||||
file1
|
|
||||||
dir/file2
|
|
||||||
Non-recursive:
|
|
||||||
file1
|
|
||||||
Dirs:
|
|
||||||
dir
|
|
||||||
filesize: 11
|
|
||||||
contents: hello world
|
|
|
@ -1,20 +0,0 @@
|
||||||
|
|
||||||
File: Makefile
|
|
||||||
Size: 828
|
|
||||||
First line: GCC=g++ -I../
|
|
||||||
|
|
||||||
File: ogre_resource_test.cpp
|
|
||||||
Size: 1437
|
|
||||||
First line: #include <iostream>
|
|
||||||
|
|
||||||
File: bleh
|
|
||||||
Does not exist
|
|
||||||
|
|
||||||
All source files:
|
|
||||||
physfs_server_test.cpp
|
|
||||||
dummy_test.cpp
|
|
||||||
ogre_resource_test.cpp
|
|
||||||
server_common.cpp
|
|
||||||
dummy_vfs.cpp
|
|
||||||
ogre_client_test.cpp
|
|
||||||
ogre_server_test.cpp
|
|
|
@ -1,11 +0,0 @@
|
||||||
|
|
||||||
File: Makefile
|
|
||||||
Size: 828
|
|
||||||
First 12 bytes: GCC=g++ -I..
|
|
||||||
|
|
||||||
File: testfile.txt
|
|
||||||
Size: 13
|
|
||||||
First 12 bytes: hello world!
|
|
||||||
|
|
||||||
File: blah_bleh
|
|
||||||
File doesn't exist
|
|
|
@ -1,11 +0,0 @@
|
||||||
|
|
||||||
File: Makefile
|
|
||||||
Size: 828
|
|
||||||
First 12 bytes: GCC=g++ -I..
|
|
||||||
|
|
||||||
File: testfile.txt
|
|
||||||
Size: 13
|
|
||||||
First 12 bytes: hello world!
|
|
||||||
|
|
||||||
File: blah_bleh
|
|
||||||
File doesn't exist
|
|
|
@ -1,21 +0,0 @@
|
||||||
#include "../servers/physfs_vfs.hpp"
|
|
||||||
|
|
||||||
#include "server_common.cpp"
|
|
||||||
|
|
||||||
#include <physfs.h>
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
// Set up the library and paths
|
|
||||||
PHYSFS_init("blah");
|
|
||||||
PHYSFS_addToSearchPath("test.zip", 1);
|
|
||||||
PHYSFS_addToSearchPath("./", 1);
|
|
||||||
|
|
||||||
// Create our interface
|
|
||||||
PhysVFS vfs;
|
|
||||||
|
|
||||||
// Run the test
|
|
||||||
testAll(vfs);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
using namespace Mangle::VFS;
|
|
||||||
using namespace Mangle::Stream;
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
void find(VFS &vfs, const std::string &file)
|
|
||||||
{
|
|
||||||
cout << "\nFile: " << file << endl;
|
|
||||||
|
|
||||||
if(!vfs.isFile(file))
|
|
||||||
{
|
|
||||||
cout << "File doesn't exist\n";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
StreamPtr data = vfs.open(file);
|
|
||||||
|
|
||||||
cout << "Size: " << data->size() << endl;
|
|
||||||
|
|
||||||
char buf[13];
|
|
||||||
buf[12] = 0;
|
|
||||||
data->read(buf, 12);
|
|
||||||
|
|
||||||
cout << "First 12 bytes: " << buf << "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
void testAll(VFS &vfs)
|
|
||||||
{
|
|
||||||
find(vfs, "Makefile"); // From the file system
|
|
||||||
find(vfs, "testfile.txt"); // From the zip
|
|
||||||
find(vfs, "blah_bleh"); // Doesn't exist
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
make || exit
|
|
||||||
|
|
||||||
mkdir -p output
|
|
||||||
|
|
||||||
PROGS=*_test
|
|
||||||
|
|
||||||
for a in $PROGS; do
|
|
||||||
if [ -f "output/$a.out" ]; then
|
|
||||||
echo "Running $a:"
|
|
||||||
./$a | diff output/$a.out -
|
|
||||||
else
|
|
||||||
echo "Creating $a.out"
|
|
||||||
./$a > "output/$a.out"
|
|
||||||
git add "output/$a.out"
|
|
||||||
fi
|
|
||||||
done
|
|
Binary file not shown.
|
@ -1,87 +0,0 @@
|
||||||
#ifndef MANGLE_VFS_H
|
|
||||||
#define MANGLE_VFS_H
|
|
||||||
|
|
||||||
#include "../stream/stream.hpp"
|
|
||||||
#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;
|
|
||||||
|
|
||||||
typedef boost::shared_ptr<FileInfo> FileInfoPtr;
|
|
||||||
typedef boost::shared_ptr<FileInfoList> FileInfoListPtr;
|
|
||||||
|
|
||||||
/** 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 list() function work
|
|
||||||
bool hasList;
|
|
||||||
|
|
||||||
/// If true, the find() function 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 (letting all the
|
|
||||||
/// pointers to it go out of scope) should be enough to close it.
|
|
||||||
virtual Stream::StreamPtr 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 FileInfoPtr 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 FileInfoListPtr 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 FileInfoListPtr find(const std::string& pattern,
|
|
||||||
bool recursive=true,
|
|
||||||
bool dirs=false) const = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef boost::shared_ptr<VFS> VFSPtr;
|
|
||||||
|
|
||||||
}} // namespaces
|
|
||||||
#endif
|
|
Loading…
Reference in a new issue