aboutsummaryrefslogtreecommitdiff
path: root/src/stable/streamstack.h
blob: 36c2e113e1423a61ae1d07376054bfae0c87873d (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
135
136
137
138
139
140
141
142
143
144
/*
 * Copyright (C) 2007-2012 Xagasoft, All rights reserved.
 *
 * This file is part of the libbu++ library and is released under the
 * terms of the license contained in the file LICENSE.
 */

#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 Bu::size read( void *pBuf, Bu::size nBytes );
		virtual Bu::size write( const void *pBuf, Bu::size nBytes );

		virtual Bu::size write( const Bu::String &sBuf );
		virtual Bu::size tell();
		virtual void seek( Bu::size offset );
		virtual void setPos( Bu::size pos );
		virtual void setPosEnd( Bu::size 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( Bu::size iSize );
		virtual size getSize() const;
		virtual size getBlockSize() const;
		virtual Bu::String getLocation() const;

	private:
		void checkStack() const;

	private:
		FilterList lFilts;
	};
};

#endif