mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-22 13:23:55 +00:00
Added writing capability to streams. Created OutFileStream.
This commit is contained in:
parent
21d399cb81
commit
71366d9a07
12 changed files with 225 additions and 8 deletions
|
@ -23,6 +23,10 @@ class Mangle2OgreStream : public Ogre::DataStream
|
|||
// 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:
|
||||
|
@ -39,6 +43,9 @@ class Mangle2OgreStream : public Ogre::DataStream
|
|||
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);
|
||||
|
|
|
@ -23,12 +23,14 @@ class PureFilter : public Stream
|
|||
{
|
||||
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 seek(size_t pos) { src->seek(pos); }
|
||||
size_t tell() const { return src->tell(); }
|
||||
size_t size() const { return src->size(); }
|
||||
|
|
|
@ -27,6 +27,7 @@ class SliceStream : public Stream
|
|||
hasPosition = true;
|
||||
hasSize = true;
|
||||
hasPtr = src->hasPtr;
|
||||
isWritable = src->isWritable;
|
||||
}
|
||||
|
||||
size_t read(void *buf, size_t count)
|
||||
|
@ -35,7 +36,7 @@ class SliceStream : public Stream
|
|||
if(count > length-pos)
|
||||
count = length-pos;
|
||||
|
||||
// Seek into place and reading
|
||||
// Seek into place and start reading
|
||||
src->seek(offset+pos);
|
||||
count = src->read(buf, count);
|
||||
|
||||
|
@ -44,6 +45,24 @@ class SliceStream : public Stream
|
|||
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;
|
||||
|
|
41
stream/servers/outfile_stream.hpp
Normal file
41
stream/servers/outfile_stream.hpp
Normal file
|
@ -0,0 +1,41 @@
|
|||
#ifndef MANGLE_STREAM_FILESERVER_H
|
||||
#define MANGLE_STREAM_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 str_exception("OutFileStream: failed to open file " + name);
|
||||
}
|
||||
~OutFileStream() { file.close(); }
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr<OutFileStream> OutFileStreamPtr;
|
||||
|
||||
}} // namespaces
|
||||
#endif
|
79
stream/servers/std_ostream.hpp
Normal file
79
stream/servers/std_ostream.hpp
Normal file
|
@ -0,0 +1,79 @@
|
|||
#ifndef MANGLE_STREAM_STDIOSERVER_H
|
||||
#define MANGLE_STREAM_STDIOSERVER_H
|
||||
|
||||
#include "../stream.hpp"
|
||||
#include <iostream>
|
||||
#include "../../tools/str_exception.hpp"
|
||||
|
||||
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 str_exception("StdOStream: " + msg); }
|
||||
|
||||
public:
|
||||
StdOStream(std::ostream *_inf)
|
||||
: inf(_inf)
|
||||
{
|
||||
isSeekable = true;
|
||||
hasPosition = true;
|
||||
hasSize = true;
|
||||
isWritable = true;
|
||||
}
|
||||
|
||||
size_t read(void*,size_t)
|
||||
{
|
||||
assert(0&&"reading not supported by StdOStream");
|
||||
}
|
||||
|
||||
size_t write(const void* buf, size_t len)
|
||||
{
|
||||
inf->write((const char*)buf, len);
|
||||
if(inf->fail())
|
||||
fail("error writing to stream");
|
||||
|
||||
// Unfortunately, stupid std::ostream doesn't have a pcount() to
|
||||
// match gcount() for input. In general the std::iostream system
|
||||
// is an idiotically designed stream library.
|
||||
return len;
|
||||
}
|
||||
|
||||
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
|
|
@ -8,7 +8,7 @@
|
|||
namespace Mangle {
|
||||
namespace Stream {
|
||||
|
||||
/** Simplest wrapper for std::istream.
|
||||
/** Simple wrapper for std::istream.
|
||||
*/
|
||||
class StdStream : public Stream
|
||||
{
|
||||
|
|
|
@ -23,13 +23,17 @@ class Stream
|
|||
/// If true, size() works
|
||||
bool hasSize;
|
||||
|
||||
/// If true, write() works. Writing through pointer operations is
|
||||
/// not supported.
|
||||
bool isWritable;
|
||||
|
||||
/// If true, the getPtr() functions work
|
||||
bool hasPtr;
|
||||
|
||||
/// Initialize all bools to false by default
|
||||
Stream() :
|
||||
isSeekable(false), hasPosition(false), hasSize(false),
|
||||
hasPtr(false) {}
|
||||
isWritable(false), hasPtr(false) {}
|
||||
|
||||
/// Virtual destructor
|
||||
virtual ~Stream() {}
|
||||
|
@ -40,6 +44,14 @@ class Stream
|
|||
*/
|
||||
virtual size_t read(void* buf, size_t count) = 0;
|
||||
|
||||
/** Write a given number of bytes from the stream. Semantics is
|
||||
similar to read(). Only valid if isWritable is true
|
||||
|
||||
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; }
|
||||
|
||||
/// Seek to an absolute position in this stream. Not all streams are
|
||||
/// seekable.
|
||||
virtual void seek(size_t pos) = 0;
|
||||
|
|
1
stream/tests/.gitignore
vendored
1
stream/tests/.gitignore
vendored
|
@ -1 +1,2 @@
|
|||
*_test
|
||||
test.file
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
GCC=g++ -I../
|
||||
|
||||
all: ogre_client_test audiere_client_test memory_server_test buffer_filter_test file_server_test slice_filter_test
|
||||
all: ogre_client_test audiere_client_test memory_server_test buffer_filter_test file_server_test slice_filter_test file_write_test
|
||||
|
||||
I_OGRE=$(shell pkg-config --cflags OGRE)
|
||||
L_OGRE=$(shell pkg-config --libs OGRE)
|
||||
|
@ -15,6 +15,9 @@ audiere_client_test: audiere_client_test.cpp ../stream.hpp ../clients/audiere_fi
|
|||
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 $@
|
||||
|
||||
|
|
41
stream/tests/file_write_test.cpp
Normal file
41
stream/tests/file_write_test.cpp
Normal file
|
@ -0,0 +1,41 @@
|
|||
#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;
|
||||
}
|
12
stream/tests/output/file_write_test.out
Normal file
12
stream/tests/output/file_write_test.out
Normal file
|
@ -0,0 +1,12 @@
|
|||
|
||||
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
|
|
@ -11,9 +11,9 @@ namespace VFS {
|
|||
/** An OGRE Archive implementation that wraps a Mangle::VFS
|
||||
filesystem.
|
||||
|
||||
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.
|
||||
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
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue