Added Stream::InputStream interface, and a client implementation to Ogre::DataStream

This commit is contained in:
Nicolay Korslund 2009-12-19 08:26:01 +01:00
parent 325f2f17b3
commit 7139f5284d
9 changed files with 267 additions and 3 deletions

View file

@ -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

View 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

View 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
View 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
View file

@ -0,0 +1 @@
*_test

15
stream/tests/Makefile Normal file
View 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

View 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; }
};

View 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;
}

View 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;
}