forked from mirror/openmw-tes3mp
Added Stream::InputStream interface, and a client implementation to Ogre::DataStream
This commit is contained in:
parent
325f2f17b3
commit
7139f5284d
9 changed files with 267 additions and 3 deletions
|
@ -18,9 +18,9 @@ individually as separate libraries.
|
||||||
However, Mangle does NOT actually implement a game engine, or any new
|
However, Mangle does NOT actually implement a game engine, or any new
|
||||||
fundamental functionality. More on that below.
|
fundamental functionality. More on that below.
|
||||||
|
|
||||||
Currently there is only the Sound module, but more will come in the
|
Currently there's modules for sound and streams / archives (file
|
||||||
future (including input, 2D/3D graphics, GUI, physics, file
|
access). More will come in the future (including input, 2D/3D
|
||||||
system/archive access, and more.)
|
graphics, GUI, physics, and more.)
|
||||||
|
|
||||||
|
|
||||||
Main idea
|
Main idea
|
||||||
|
|
30
stream/imp_client/iwrapper.h
Normal file
30
stream/imp_client/iwrapper.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#ifndef MANGLE_STREAM_IWRAPPER_H
|
||||||
|
#define MANGLE_STREAM_IWRAPPER_H
|
||||||
|
|
||||||
|
#include "../input.h"
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
namespace Mangle {
|
||||||
|
namespace Stream {
|
||||||
|
|
||||||
|
/** A generic wrapper class for a Stream::Input object.
|
||||||
|
|
||||||
|
This is used by other implementations.
|
||||||
|
*/
|
||||||
|
class _IWrapper
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
bool autoDel;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
InputStream *inp;
|
||||||
|
|
||||||
|
public:
|
||||||
|
_IWrapper(InputStream *_inp, bool _autoDel = false)
|
||||||
|
: inp(_inp), autoDel(_autoDel) { assert(inp != NULL); }
|
||||||
|
|
||||||
|
virtual ~_IWrapper() { if(autoDel) delete inp; }
|
||||||
|
};
|
||||||
|
|
||||||
|
}} // namespaces
|
||||||
|
#endif
|
60
stream/imp_client/ogre_datastream.h
Normal file
60
stream/imp_client/ogre_datastream.h
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
#ifndef MANGLE_STREAM_OGRECLIENT_H
|
||||||
|
#define MANGLE_STREAM_OGRECLIENT_H
|
||||||
|
|
||||||
|
#include <OgreDataStream.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include "iwrapper.h"
|
||||||
|
|
||||||
|
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 MangleDataStream : public Ogre::DataStream, _IWrapper
|
||||||
|
{
|
||||||
|
void init()
|
||||||
|
{
|
||||||
|
// Get the size, if possible
|
||||||
|
if(inp->hasSize)
|
||||||
|
mSize = inp->size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// Constructor without name
|
||||||
|
MangleDataStream(InputStream *inp, bool autoDel=false)
|
||||||
|
: _IWrapper(inp, autoDel) { init(); }
|
||||||
|
|
||||||
|
/// Constructor for a named data stream
|
||||||
|
MangleDataStream(const Ogre::String &name, InputStream *inp, bool autoDel=false)
|
||||||
|
: _IWrapper(inp, autoDel), Ogre::DataStream(name) { init(); }
|
||||||
|
|
||||||
|
|
||||||
|
// Only implement the DataStream functions we have to implement
|
||||||
|
|
||||||
|
size_t read(void *buf, size_t count)
|
||||||
|
{ return inp->read(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
|
50
stream/input.h
Normal file
50
stream/input.h
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
#ifndef MANGLE_STREAM_INPUT_H
|
||||||
|
#define MANGLE_STREAM_INPUT_H
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
namespace Mangle {
|
||||||
|
namespace Stream {
|
||||||
|
|
||||||
|
/// An abstract interface for a stream data.
|
||||||
|
class InputStream
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
|
||||||
|
/// Virtual destructor
|
||||||
|
virtual ~InputStream() {}
|
||||||
|
|
||||||
|
/** 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.
|
||||||
|
*/
|
||||||
|
virtual size_t read(void* buf, size_t count) = 0;
|
||||||
|
|
||||||
|
/// Seek to an absolute position in this stream. Not all streams are
|
||||||
|
/// seekable.
|
||||||
|
virtual void seek(size_t pos) = 0;
|
||||||
|
|
||||||
|
/// Get the current position in the stream. Non-seekable streams are
|
||||||
|
/// not required to keep track of this.
|
||||||
|
virtual size_t tell() const = 0;
|
||||||
|
|
||||||
|
/// Return the total size of the stream. For streams where this is
|
||||||
|
/// not applicable, size() should return zero.
|
||||||
|
virtual size_t size() const = 0;
|
||||||
|
|
||||||
|
/// Returns true if the stream is empty
|
||||||
|
virtual bool eof() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
}} // namespaces
|
||||||
|
#endif
|
1
stream/tests/.gitignore
vendored
Normal file
1
stream/tests/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
*_test
|
15
stream/tests/Makefile
Normal file
15
stream/tests/Makefile
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
GCC=g++ -I../ -I../imp_client/
|
||||||
|
|
||||||
|
all: ogre_client_test dummy_test
|
||||||
|
|
||||||
|
I_OGRE=$(shell pkg-config --cflags OGRE)
|
||||||
|
L_OGRE=$(shell pkg-config --libs OGRE)
|
||||||
|
|
||||||
|
ogre_client_test: ogre_client_test.cpp dummy_input.cpp ../input.h ../imp_client/iwrapper.h ../imp_client/ogre_datastream.h
|
||||||
|
$(GCC) $< -o $@ $(I_OGRE) $(L_OGRE)
|
||||||
|
|
||||||
|
dummy_test: dummy_test.cpp dummy_input.cpp ../input.h
|
||||||
|
$(GCC) $< -o $@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm *_test
|
48
stream/tests/dummy_input.cpp
Normal file
48
stream/tests/dummy_input.cpp
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
// This file is shared between several test programs
|
||||||
|
#include "input.h"
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
using namespace Mangle::Stream;
|
||||||
|
|
||||||
|
// A simple dummy stream
|
||||||
|
const char _data[12] = "hello world";
|
||||||
|
|
||||||
|
class DummyInput : public InputStream
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
int pos;
|
||||||
|
|
||||||
|
public:
|
||||||
|
DummyInput() : pos(0)
|
||||||
|
{
|
||||||
|
isSeekable = true;
|
||||||
|
hasPosition = true;
|
||||||
|
hasSize = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t read(void *buf, size_t count)
|
||||||
|
{
|
||||||
|
assert(pos >= 0 && pos <= 11);
|
||||||
|
if(count+pos > 11)
|
||||||
|
count = 11-pos;
|
||||||
|
assert(count <= 11);
|
||||||
|
|
||||||
|
memcpy(buf, _data+pos, count);
|
||||||
|
pos += count;
|
||||||
|
|
||||||
|
assert(pos >= 0 && pos <= 11);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void seek(size_t npos)
|
||||||
|
{
|
||||||
|
if(npos > 11) npos = 11;
|
||||||
|
pos = npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t tell() const { return pos; }
|
||||||
|
size_t size() const { return 11; }
|
||||||
|
|
||||||
|
bool eof() const { return pos == 11; }
|
||||||
|
};
|
39
stream/tests/dummy_test.cpp
Normal file
39
stream/tests/dummy_test.cpp
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
#include "dummy_input.cpp"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
InputStream *inp = new DummyInput();
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
21
stream/tests/ogre_client_test.cpp
Normal file
21
stream/tests/ogre_client_test.cpp
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
#include "dummy_input.cpp"
|
||||||
|
#include "ogre_datastream.h"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
using namespace Ogre;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
InputStream *inp = new DummyInput();
|
||||||
|
DataStreamPtr p(new MangleDataStream("hello", inp, true));
|
||||||
|
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;
|
||||||
|
}
|
Loading…
Reference in a new issue