diff --git a/stream/filters/buffer_stream.h b/stream/filters/buffer_stream.h index f8290ea5e..7790a7542 100644 --- a/stream/filters/buffer_stream.h +++ b/stream/filters/buffer_stream.h @@ -2,20 +2,63 @@ #define MANGLE_STREAM_BUFFER_H #include "../servers/memory_stream.h" -#include "../clients/iwrapper.h" +#include namespace Mangle { namespace Stream { /** A Stream that reads another Stream into a buffer, and serves it as - a MemoryStream. + a MemoryStream. Might be expanded with other capabilities later. */ class BufferStream : public MemoryStream { + std::vector buffer; + public: BufferStream(Stream *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. + const int ADD = 32*1024; + 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 || 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()); } }; diff --git a/stream/servers/memory_stream.h b/stream/servers/memory_stream.h index c47ffa535..03f7a42f2 100644 --- a/stream/servers/memory_stream.h +++ b/stream/servers/memory_stream.h @@ -3,15 +3,14 @@ #include #include "../stream.h" -#include namespace Mangle { namespace Stream { // Do this before the class declaration, since the class itself -// depends on it -class MemoryStream; -typedef boost::shared_ptr MemoryStreamPtr; +// depends on it. TODO: Postponed for later +//class MemoryStream; +//typedef boost::shared_ptr MemoryStreamPtr; /** A Stream wrapping a memory buffer @@ -33,7 +32,7 @@ class MemoryStream : public Stream } MemoryStream() - : data(NULL), length(0), pos(0); + : data(NULL), length(0), pos(0) { isSeekable = true; hasPosition = true; @@ -89,10 +88,12 @@ class MemoryStream : public Stream No memory is copied during this operation, the new stream is just another 'view' into the same shared memory buffer. + + TODO: Rewrite to use smart pointers */ - MemoryStreamPtr clone(bool setPos=false) const + MemoryStream* clone(bool setPos=false) const { - MemoryStreamPtr res = new MemoryStream(data, length); + MemoryStream* res = new MemoryStream(data, length); if(setPos) res->seek(pos); return res; } diff --git a/stream/tests/Makefile b/stream/tests/Makefile index 8006572bd..c86a7397f 100644 --- a/stream/tests/Makefile +++ b/stream/tests/Makefile @@ -15,5 +15,8 @@ audiere_client_test: audiere_client_test.cpp ../stream.h ../clients/iwrapper.h . memory_test: memory_test.cpp ../stream.h ../servers/memory_stream.h $(GCC) $< -o $@ +buffer_test: buffer_test.cpp ../stream.h ../servers/memory_stream.h ../filters/buffer_stream.h + $(GCC) $< -o $@ + clean: rm *_test diff --git a/stream/tests/buffer_test.cpp b/stream/tests/buffer_test.cpp new file mode 100644 index 000000000..24bb7e070 --- /dev/null +++ b/stream/tests/buffer_test.cpp @@ -0,0 +1,41 @@ +#include +#include + +#include "../filters/buffer_stream.h" + +using namespace Mangle::Stream; +using namespace std; + +int main() +{ + Stream *orig = new MemoryStream("hello world", 11); + Stream *inp = new BufferStream(orig); + + 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; +}