diff options
| -rw-r--r-- | default.bld | 2 | ||||
| -rw-r--r-- | src/streamstack.cpp | 120 | ||||
| -rw-r--r-- | src/streamstack.h | 89 | ||||
| -rw-r--r-- | src/tests/streamstack.cpp | 93 |
4 files changed, 302 insertions, 2 deletions
diff --git a/default.bld b/default.bld index cb5a4d9..857e988 100644 --- a/default.bld +++ b/default.bld | |||
| @@ -97,7 +97,7 @@ target files("src/tests/*.cpp").replace("src/","").replace(".cpp","") | |||
| 97 | 97 | ||
| 98 | // Some tests need extra libs and whatnot, that goes here. | 98 | // Some tests need extra libs and whatnot, that goes here. |
| 99 | 99 | ||
| 100 | target "tests/bzip2" | 100 | target ["tests/bzip2", "tests/streamstack"] |
| 101 | { | 101 | { |
| 102 | LDFLAGS += "-lbz2"; | 102 | LDFLAGS += "-lbz2"; |
| 103 | } | 103 | } |
diff --git a/src/streamstack.cpp b/src/streamstack.cpp index 9e45cc4..c7f8af5 100644 --- a/src/streamstack.cpp +++ b/src/streamstack.cpp | |||
| @@ -4,83 +4,203 @@ Bu::StreamStack::StreamStack() | |||
| 4 | { | 4 | { |
| 5 | } | 5 | } |
| 6 | 6 | ||
| 7 | Bu::StreamStack::StreamStack( Bu::Stream *pStream ) | ||
| 8 | { | ||
| 9 | lFilts.prepend( pStream ); | ||
| 10 | } | ||
| 11 | |||
| 7 | Bu::StreamStack::~StreamStack() | 12 | Bu::StreamStack::~StreamStack() |
| 8 | { | 13 | { |
| 14 | clearStack(); | ||
| 15 | } | ||
| 16 | |||
| 17 | bool Bu::StreamStack::isEmpty() | ||
| 18 | { | ||
| 19 | return lFilts.isEmpty(); | ||
| 20 | } | ||
| 21 | |||
| 22 | bool Bu::StreamStack::hasStream() | ||
| 23 | { | ||
| 24 | return !lFilts.isEmpty(); | ||
| 25 | } | ||
| 26 | |||
| 27 | void Bu::StreamStack::setStream( Bu::Stream *pStream ) | ||
| 28 | { | ||
| 29 | if( !lFilts.isEmpty() ) | ||
| 30 | throw Bu::ExceptionBase("There is already a stream set."); | ||
| 31 | |||
| 32 | lFilts.prepend( pStream ); | ||
| 33 | } | ||
| 34 | |||
| 35 | void Bu::StreamStack::clearStack() | ||
| 36 | { | ||
| 37 | for( FilterList::iterator i = lFilts.begin(); i; i++ ) | ||
| 38 | { | ||
| 39 | delete *i; | ||
| 40 | } | ||
| 41 | |||
| 42 | lFilts.clear(); | ||
| 43 | } | ||
| 44 | |||
| 45 | void Bu::StreamStack::popFilter() | ||
| 46 | { | ||
| 47 | if( lFilts.isEmpty() ) | ||
| 48 | return; | ||
| 49 | |||
| 50 | delete lFilts.first(); | ||
| 51 | lFilts.erase( lFilts.begin() ); | ||
| 52 | } | ||
| 53 | |||
| 54 | Bu::Stream *Bu::StreamStack::getTop() | ||
| 55 | { | ||
| 56 | checkStack(); | ||
| 57 | |||
| 58 | return lFilts.first(); | ||
| 59 | } | ||
| 60 | |||
| 61 | Bu::Stream *Bu::StreamStack::getStream() | ||
| 62 | { | ||
| 63 | checkStack(); | ||
| 64 | |||
| 65 | return lFilts.last(); | ||
| 9 | } | 66 | } |
| 10 | 67 | ||
| 11 | void Bu::StreamStack::close() | 68 | void Bu::StreamStack::close() |
| 12 | { | 69 | { |
| 70 | checkStack(); | ||
| 71 | |||
| 72 | lFilts.first()->close(); | ||
| 13 | } | 73 | } |
| 14 | 74 | ||
| 15 | size_t Bu::StreamStack::read( void *pBuf, size_t nBytes ) | 75 | size_t Bu::StreamStack::read( void *pBuf, size_t nBytes ) |
| 16 | { | 76 | { |
| 77 | checkStack(); | ||
| 78 | |||
| 79 | return lFilts.first()->read( pBuf, nBytes ); | ||
| 17 | } | 80 | } |
| 18 | 81 | ||
| 19 | size_t Bu::StreamStack::write( const void *pBuf, size_t nBytes ) | 82 | size_t Bu::StreamStack::write( const void *pBuf, size_t nBytes ) |
| 20 | { | 83 | { |
| 84 | checkStack(); | ||
| 85 | |||
| 86 | return lFilts.first()->write( pBuf, nBytes ); | ||
| 21 | } | 87 | } |
| 22 | 88 | ||
| 23 | size_t Bu::StreamStack::write( const Bu::FString &sBuf ) | 89 | size_t Bu::StreamStack::write( const Bu::FString &sBuf ) |
| 24 | { | 90 | { |
| 91 | checkStack(); | ||
| 92 | |||
| 93 | return lFilts.first()->write( sBuf ); | ||
| 25 | } | 94 | } |
| 26 | 95 | ||
| 27 | long Bu::StreamStack::tell() | 96 | long Bu::StreamStack::tell() |
| 28 | { | 97 | { |
| 98 | checkStack(); | ||
| 99 | |||
| 100 | return lFilts.first()->tell(); | ||
| 29 | } | 101 | } |
| 30 | 102 | ||
| 31 | void Bu::StreamStack::seek( long offset ) | 103 | void Bu::StreamStack::seek( long offset ) |
| 32 | { | 104 | { |
| 105 | checkStack(); | ||
| 106 | |||
| 107 | lFilts.first()->seek( offset ); | ||
| 33 | } | 108 | } |
| 34 | 109 | ||
| 35 | void Bu::StreamStack::setPos( long pos ) | 110 | void Bu::StreamStack::setPos( long pos ) |
| 36 | { | 111 | { |
| 112 | checkStack(); | ||
| 113 | |||
| 114 | lFilts.first()->setPos( pos ); | ||
| 37 | } | 115 | } |
| 38 | 116 | ||
| 39 | void Bu::StreamStack::setPosEnd( long pos ) | 117 | void Bu::StreamStack::setPosEnd( long pos ) |
| 40 | { | 118 | { |
| 119 | checkStack(); | ||
| 120 | |||
| 121 | lFilts.first()->setPosEnd( pos ); | ||
| 41 | } | 122 | } |
| 42 | 123 | ||
| 43 | bool Bu::StreamStack::isEos() | 124 | bool Bu::StreamStack::isEos() |
| 44 | { | 125 | { |
| 126 | checkStack(); | ||
| 127 | |||
| 128 | return lFilts.first()->isEos(); | ||
| 45 | } | 129 | } |
| 46 | 130 | ||
| 47 | bool Bu::StreamStack::isOpen() | 131 | bool Bu::StreamStack::isOpen() |
| 48 | { | 132 | { |
| 133 | checkStack(); | ||
| 134 | |||
| 135 | return lFilts.first()->isOpen(); | ||
| 49 | } | 136 | } |
| 50 | 137 | ||
| 51 | void Bu::StreamStack::flush() | 138 | void Bu::StreamStack::flush() |
| 52 | { | 139 | { |
| 140 | checkStack(); | ||
| 141 | |||
| 142 | lFilts.first()->flush(); | ||
| 53 | } | 143 | } |
| 54 | 144 | ||
| 55 | bool Bu::StreamStack::canRead() | 145 | bool Bu::StreamStack::canRead() |
| 56 | { | 146 | { |
| 147 | checkStack(); | ||
| 148 | |||
| 149 | return lFilts.first()->canRead(); | ||
| 57 | } | 150 | } |
| 58 | 151 | ||
| 59 | bool Bu::StreamStack::canWrite() | 152 | bool Bu::StreamStack::canWrite() |
| 60 | { | 153 | { |
| 154 | checkStack(); | ||
| 155 | |||
| 156 | return lFilts.first()->canWrite(); | ||
| 61 | } | 157 | } |
| 62 | 158 | ||
| 63 | bool Bu::StreamStack::isReadable() | 159 | bool Bu::StreamStack::isReadable() |
| 64 | { | 160 | { |
| 161 | checkStack(); | ||
| 162 | |||
| 163 | return lFilts.first()->isReadable(); | ||
| 65 | } | 164 | } |
| 66 | 165 | ||
| 67 | bool Bu::StreamStack::isWritable() | 166 | bool Bu::StreamStack::isWritable() |
| 68 | { | 167 | { |
| 168 | checkStack(); | ||
| 169 | |||
| 170 | return lFilts.first()->isWritable(); | ||
| 69 | } | 171 | } |
| 70 | 172 | ||
| 71 | bool Bu::StreamStack::isSeekable() | 173 | bool Bu::StreamStack::isSeekable() |
| 72 | { | 174 | { |
| 175 | checkStack(); | ||
| 176 | |||
| 177 | return lFilts.first()->isSeekable(); | ||
| 73 | } | 178 | } |
| 74 | 179 | ||
| 75 | bool Bu::StreamStack::isBlocking() | 180 | bool Bu::StreamStack::isBlocking() |
| 76 | { | 181 | { |
| 182 | checkStack(); | ||
| 183 | |||
| 184 | return lFilts.first()->isBlocking(); | ||
| 77 | } | 185 | } |
| 78 | 186 | ||
| 79 | void Bu::StreamStack::setBlocking( bool bBlocking ) | 187 | void Bu::StreamStack::setBlocking( bool bBlocking ) |
| 80 | { | 188 | { |
| 189 | checkStack(); | ||
| 190 | |||
| 191 | lFilts.first()->setBlocking( bBlocking ); | ||
| 81 | } | 192 | } |
| 82 | 193 | ||
| 83 | void Bu::StreamStack::setSize( long iSize ) | 194 | void Bu::StreamStack::setSize( long iSize ) |
| 84 | { | 195 | { |
| 196 | checkStack(); | ||
| 197 | |||
| 198 | lFilts.first()->setSize( iSize ); | ||
| 199 | } | ||
| 200 | |||
| 201 | inline void Bu::StreamStack::checkStack() | ||
| 202 | { | ||
| 203 | if( lFilts.isEmpty() ) | ||
| 204 | throw Bu::ExceptionBase("StreamStack is empty."); | ||
| 85 | } | 205 | } |
| 86 | 206 | ||
diff --git a/src/streamstack.h b/src/streamstack.h index 03d8d8f..89e683d 100644 --- a/src/streamstack.h +++ b/src/streamstack.h | |||
| @@ -3,14 +3,99 @@ | |||
| 3 | 3 | ||
| 4 | #include "bu/stream.h" | 4 | #include "bu/stream.h" |
| 5 | 5 | ||
| 6 | #include <typeinfo> | ||
| 7 | |||
| 6 | namespace Bu | 8 | namespace Bu |
| 7 | { | 9 | { |
| 8 | class StreamStack : public Bu::Stream | 10 | class StreamStack : public Bu::Stream |
| 9 | { | 11 | { |
| 12 | private: | ||
| 13 | typedef Bu::List<Bu::Stream *> FilterList; | ||
| 14 | |||
| 10 | public: | 15 | public: |
| 11 | StreamStack(); | 16 | StreamStack(); |
| 17 | StreamStack( Bu::Stream *pStream ); | ||
| 12 | virtual ~StreamStack(); | 18 | virtual ~StreamStack(); |
| 13 | 19 | ||
| 20 | bool isEmpty(); | ||
| 21 | bool hasStream(); | ||
| 22 | void setStream( Bu::Stream *pStream ); | ||
| 23 | |||
| 24 | void clearStack(); | ||
| 25 | void popFilter(); | ||
| 26 | Bu::Stream *getTop(); | ||
| 27 | |||
| 28 | Bu::Stream *getStream(); | ||
| 29 | |||
| 30 | template<typename filter> | ||
| 31 | Bu::Stream *findFilter() | ||
| 32 | { | ||
| 33 | for( FilterList::iterator i = lFilts.begin(); i; i++ ) | ||
| 34 | { | ||
| 35 | if( typeid(**i) == typeid( filter ) ) | ||
| 36 | { | ||
| 37 | return *i; | ||
| 38 | } | ||
| 39 | } | ||
| 40 | |||
| 41 | throw Bu::ExceptionBase("Filter not found."); | ||
| 42 | } | ||
| 43 | |||
| 44 | template<typename filter> | ||
| 45 | void pushFilter() | ||
| 46 | { | ||
| 47 | checkStack(); | ||
| 48 | |||
| 49 | filter *pFlt = new filter( *lFilts.first() ); | ||
| 50 | lFilts.prepend( pFlt ); | ||
| 51 | } | ||
| 52 | |||
| 53 | template<typename filter, typename p1t> | ||
| 54 | void pushFilter( p1t p1 ) | ||
| 55 | { | ||
| 56 | checkStack(); | ||
| 57 | |||
| 58 | filter *pFlt = new filter( *lFilts.first(), p1 ); | ||
| 59 | lFilts.prepend( pFlt ); | ||
| 60 | } | ||
| 61 | |||
| 62 | template<typename filter, typename p1t, typename p2t> | ||
| 63 | void pushFilter( p1t p1, p2t p2 ) | ||
| 64 | { | ||
| 65 | checkStack(); | ||
| 66 | |||
| 67 | filter *pFlt = new filter( *lFilts.first(), p1, p2 ); | ||
| 68 | lFilts.prepend( pFlt ); | ||
| 69 | } | ||
| 70 | |||
| 71 | template<typename filter, typename p1t, typename p2t, typename p3t> | ||
| 72 | void pushFilter( p1t p1, p2t p2, p3t p3 ) | ||
| 73 | { | ||
| 74 | checkStack(); | ||
| 75 | |||
| 76 | filter *pFlt = new filter( *lFilts.first(), p1, p2, p3 ); | ||
| 77 | lFilts.prepend( pFlt ); | ||
| 78 | } | ||
| 79 | |||
| 80 | template<typename filter, typename p1t, typename p2t, typename p3t, | ||
| 81 | typename p4t> | ||
| 82 | void pushFilter( p1t p1, p2t p2, p3t p3, p4t p4 ) | ||
| 83 | { | ||
| 84 | checkStack(); | ||
| 85 | |||
| 86 | filter *pFlt = new filter( *lFilts.first(), p1, p2, p3, p4 ); | ||
| 87 | lFilts.prepend( pFlt ); | ||
| 88 | } | ||
| 89 | |||
| 90 | template<typename filter, typename p1t, typename p2t, typename p3t, | ||
| 91 | typename p4t, typename p5t> | ||
| 92 | void pushFilter( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5 ) | ||
| 93 | { | ||
| 94 | checkStack(); | ||
| 95 | |||
| 96 | filter *pFlt = new filter( *lFilts.first(), p1, p2, p3, p4, p5 ); | ||
| 97 | lFilts.prepend( pFlt ); | ||
| 98 | } | ||
| 14 | 99 | ||
| 15 | // | 100 | // |
| 16 | // Everything below here merely passes on the call to the top of the | 101 | // Everything below here merely passes on the call to the top of the |
| @@ -39,7 +124,9 @@ namespace Bu | |||
| 39 | virtual void setSize( long iSize ); | 124 | virtual void setSize( long iSize ); |
| 40 | 125 | ||
| 41 | private: | 126 | private: |
| 42 | typedef Bu::List<Bu::Stream *> FilterList; | 127 | void checkStack(); |
| 128 | |||
| 129 | private: | ||
| 43 | FilterList lFilts; | 130 | FilterList lFilts; |
| 44 | }; | 131 | }; |
| 45 | }; | 132 | }; |
diff --git a/src/tests/streamstack.cpp b/src/tests/streamstack.cpp new file mode 100644 index 0000000..56a7076 --- /dev/null +++ b/src/tests/streamstack.cpp | |||
| @@ -0,0 +1,93 @@ | |||
| 1 | #include "bu/streamstack.h" | ||
| 2 | |||
| 3 | #include "bu/file.h" | ||
| 4 | #include "bu/base64.h" | ||
| 5 | #include "bu/bzip2.h" | ||
| 6 | |||
| 7 | #include "bu/sio.h" | ||
| 8 | |||
| 9 | #include <time.h> | ||
| 10 | |||
| 11 | using namespace Bu; | ||
| 12 | |||
| 13 | class DoStuff | ||
| 14 | { | ||
| 15 | public: | ||
| 16 | DoStuff( Bu::Stream &rStream ) : | ||
| 17 | rStream( rStream ) | ||
| 18 | { | ||
| 19 | } | ||
| 20 | |||
| 21 | virtual ~DoStuff() | ||
| 22 | { | ||
| 23 | } | ||
| 24 | |||
| 25 | void write() | ||
| 26 | { | ||
| 27 | Bu::FString s; | ||
| 28 | time_t tNow = time( NULL ); | ||
| 29 | s = ctime( &tNow ); | ||
| 30 | long lSize = s.getSize()-1; | ||
| 31 | rStream.write( &lSize, sizeof(long) ); | ||
| 32 | rStream.write( s.getStr(), lSize ); | ||
| 33 | } | ||
| 34 | |||
| 35 | void read() | ||
| 36 | { | ||
| 37 | Bu::FString s; | ||
| 38 | long lSize; | ||
| 39 | rStream.read( &lSize, sizeof(long) ); | ||
| 40 | s.setSize( lSize ); | ||
| 41 | rStream.read( s.getStr(), lSize ); | ||
| 42 | sio << "Read str(" << lSize << ") = '" << s << "'" << sio.nl; | ||
| 43 | } | ||
| 44 | |||
| 45 | private: | ||
| 46 | Bu::Stream &rStream; | ||
| 47 | }; | ||
| 48 | |||
| 49 | int main() | ||
| 50 | { | ||
| 51 | Bu::StreamStack ss; | ||
| 52 | |||
| 53 | DoStuff ds( ss ); | ||
| 54 | |||
| 55 | try | ||
| 56 | { | ||
| 57 | ds.write(); | ||
| 58 | sio << "This shouldn't have worked." << sio.nl; | ||
| 59 | } | ||
| 60 | catch( Bu::ExceptionBase &e ) | ||
| 61 | { | ||
| 62 | sio << "Got exception, this is good: " << e.what() << sio.nl; | ||
| 63 | } | ||
| 64 | |||
| 65 | ss.setStream( new Bu::File("Hello.test", Bu::File::WriteNew ) ); | ||
| 66 | |||
| 67 | ds.write(); | ||
| 68 | |||
| 69 | ss.pushFilter<Bu::Base64>(); | ||
| 70 | |||
| 71 | ds.write(); | ||
| 72 | |||
| 73 | ss.pushFilter<Bu::BZip2>(); | ||
| 74 | |||
| 75 | ds.write(); | ||
| 76 | |||
| 77 | ss.clearStack(); | ||
| 78 | |||
| 79 | ss.setStream( new Bu::File("Hello.test", Bu::File::Read ) ); | ||
| 80 | |||
| 81 | ds.read(); | ||
| 82 | |||
| 83 | ss.pushFilter<Bu::Base64>(); | ||
| 84 | |||
| 85 | ds.read(); | ||
| 86 | |||
| 87 | ss.pushFilter<Bu::BZip2>(); | ||
| 88 | |||
| 89 | ds.read(); | ||
| 90 | |||
| 91 | return 0; | ||
| 92 | } | ||
| 93 | |||
