summaryrefslogtreecommitdiff
path: root/src/streamstack.h
blob: 2554bd2d498e6e0aafb237dfdf509445a71afc76 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#ifndef BU_STREAM_STACK_H
#define BU_STREAM_STACK_H

#include "bu/stream.h"

#include <typeinfo>

namespace Bu
{
	class StreamStack : public Bu::Stream
	{
	private:
		typedef Bu::List<Bu::Stream *> FilterList;

	public:
		StreamStack();
		StreamStack( Bu::Stream *pStream );
		virtual ~StreamStack();

		bool isEmpty();
		bool hasStream();
		void setStream( Bu::Stream *pStream );

		void clear();
		void popFilter();
		Bu::Stream *getTop();

		Bu::Stream *getStream();

		template<typename filter>
		Bu::Stream *findFilter()
		{
			for( FilterList::iterator i = lFilts.begin(); i; i++ )
			{
				if( typeid(**i) == typeid( filter ) )
				{
					return *i;
				}
			}

			throw Bu::ExceptionBase("Filter not found.");
		}

		template<typename filter>
		void pushFilter()
		{
			checkStack();

			filter *pFlt = new filter( *lFilts.first() );
			lFilts.prepend( pFlt );
		}

		template<typename filter, typename p1t>
		void pushFilter( p1t p1 )
		{
			checkStack();

			filter *pFlt = new filter( *lFilts.first(), p1 );
			lFilts.prepend( pFlt );
		}

		template<typename filter, typename p1t, typename p2t>
		void pushFilter( p1t p1, p2t p2 )
		{
			checkStack();

			filter *pFlt = new filter( *lFilts.first(), p1, p2 );
			lFilts.prepend( pFlt );
		}

		template<typename filter, typename p1t, typename p2t, typename p3t>
		void pushFilter( p1t p1, p2t p2, p3t p3 )
		{
			checkStack();

			filter *pFlt = new filter( *lFilts.first(), p1, p2, p3 );
			lFilts.prepend( pFlt );
		}

		template<typename filter, typename p1t, typename p2t, typename p3t,
			typename p4t>
		void pushFilter( p1t p1, p2t p2, p3t p3, p4t p4 )
		{
			checkStack();

			filter *pFlt = new filter( *lFilts.first(), p1, p2, p3, p4 );
			lFilts.prepend( pFlt );
		}

		template<typename filter, typename p1t, typename p2t, typename p3t,
			typename p4t, typename p5t>
		void pushFilter( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5 )
		{
			checkStack();

			filter *pFlt = new filter( *lFilts.first(), p1, p2, p3, p4, p5 );
			lFilts.prepend( pFlt );
		}

		//
		// Everything below here merely passes on the call to the top of the
		// stream stack.
		//

		virtual void close();
		virtual size_t read( void *pBuf, size_t nBytes );
		virtual size_t write( const void *pBuf, size_t nBytes );

		virtual size_t write( const Bu::String &sBuf );
		virtual long tell();
		virtual void seek( long offset );
		virtual void setPos( long pos );
		virtual void setPosEnd( long pos );
		virtual bool isEos();
		virtual bool isOpen();
		virtual void flush();
		virtual bool canRead();
		virtual bool canWrite();
		virtual bool isReadable();
		virtual bool isWritable();
		virtual bool isSeekable();
		virtual bool isBlocking();
		virtual void setBlocking( bool bBlocking=true );
		virtual void setSize( long iSize );

	private:
		void checkStack();

	private:
		FilterList lFilts;
	};
};

#endif