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
parent
7734771245
commit
2a3ce5ee6d
@ -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…
Reference in New Issue