forked from mirror/openmw-tes3mp
Merge remote branch 'zini/master' into nif-cleanup
Conflicts: components/bsa/bsa_archive.cppactorid
commit
b4c8375f3c
@ -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
|
@ -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 +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 New Issue