Remove Mangle::Stream

The base Stream class is left because some part of the terrain esm land factory
inherits from it, though it's largely unused (few of the methods work, and none
actually do anything).
actorid
Chris Robinson 13 years ago
parent 7734771245
commit 2a3ce5ee6d

@ -101,9 +101,8 @@ ENDIF()
set(LIBDIR ${CMAKE_SOURCE_DIR}/libs)
set(MANGLE_VFS ${LIBDIR}/mangle/vfs/servers/ogre_vfs.cpp)
set(MANGLE_INPUT ${LIBDIR}/mangle/input/servers/ois_driver.cpp)
set(MANGLE_ALL ${MANGLE_VFS} ${MANGLE_INPUT})
set(MANGLE_ALL ${MANGLE_INPUT})
source_group(libs\\mangle FILES ${MANGLE_ALL})
set(OENGINE_OGRE

@ -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
Loading…
Cancel
Save