Subversion Repositories spk

Rev

Rev 1 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 cycrow 1
/*
114 cycrow 2
	High level wrapper around parser <Parser>. It acts as a stream 
3
	dynamically loading and unloading tokens as required.
1 cycrow 4
*/
5
 
6
#ifndef TOKEN_STREAM_INCLUDED
7
#define TOKEN_STREAM_INCLUDED
8
 
114 cycrow 9
#include "../common/stream_base.h"
1 cycrow 10
 
114 cycrow 11
template <class Parser>
12
class token_stream : public mystream::stream_base
1 cycrow 13
{
14
	public:
114 cycrow 15
		typedef Parser parser_type;
16
		typedef typename Parser::token token;
17
		typedef typename Parser::TokenList::size_type size_type;
1 cycrow 18
		typedef int offset_type;
114 cycrow 19
		typedef typename Parser::ParseFlags ParseFlags;
20
		typedef typename Parser::Error Error;
1 cycrow 21
 
22
	private:
114 cycrow 23
		typedef typename Parser::TokenList::iterator iterator;
1 cycrow 24
 
114 cycrow 25
		Parser p;
1 cycrow 26
		iterator m_end;
27
		iterator m_pos;
28
		size_type m_left;
29
		size_type m_right;
30
 
114 cycrow 31
		ParseFlags m_parseFlags;
32
 
1 cycrow 33
		void advance(iterator &it, offset_type off)
34
		{
114 cycrow 35
			if(fail()) return;
1 cycrow 36
			if(off > 0){
37
				for(offset_type i=0; i < off; i++)
38
					++it;
39
			}
40
			else{
41
				for(offset_type i=off; i < 0; i++)
42
					--it;
43
			}
44
		}
45
 
46
		void parse(size_t limit)
47
		{
48
			m_right+=p.parseBuffer(limit);
114 cycrow 49
			if(p.error().code!=Parser::Error::errNone) 
50
				setstate(failbit);
1 cycrow 51
		}
52
 
114 cycrow 53
		void unload(size_t count=0)
1 cycrow 54
		{
55
			if(count > m_left) count=m_left;
56
			m_left-=count;
57
			while(count--){
58
				delete *(p.tokens.begin());
59
				p.tokens.erase(p.tokens.begin());
60
			}
61
		}
62
 
63
	public:
64
		static const int tokenTreshold = 200; // how much tokens to unload
65
		static const int tokenUnloadTreshold = 2 * 200; // when to start unloading tokens
66
 
114 cycrow 67
		token_stream(ParseFlags flags) { parseFlags(flags); }
68
		token_stream() { parseFlags(Parser::none); }
1 cycrow 69
 
70
		void rdbuffer(char *pszBuffer, size_t size) 
71
		{ 
114 cycrow 72
			p.parseFlags(parseFlags());
1 cycrow 73
			p.preParseBuffer(pszBuffer, size); 
74
			m_left=0;
75
			m_right=p.parseBuffer(1); 
76
			m_pos=p.tokens.begin();
77
			m_end=p.tokens.end();
114 cycrow 78
			if(p.error().code!=Parser::Error::errNone)
79
				clear(failbit);
80
			else
81
				clear(p.tokens.size() ? goodbit : eofbit); 
1 cycrow 82
		}
83
 
84
		token* tok() { return good() ? *m_pos : 0; }
85
 
86
		size_type tell() const { return m_left; }
87
		size_type avail() const { return m_right; }
88
		size_type size() const { return p.tokens.size(); }
89
 
90
		token_stream& operator++()	{ advance(); return *this; }
91
		token_stream& operator--()	{ advance(-1); return *this; }
92
 
114 cycrow 93
		Error parseError() const { return p.error(); }
1 cycrow 94
 
114 cycrow 95
		ParseFlags parseFlags() const { return m_parseFlags; }
96
		void parseFlags(ParseFlags flags) { m_parseFlags=flags; }
97
 
1 cycrow 98
		bool advance(offset_type offset=1)
99
		{
100
			if(offset > (offset_type)m_right)
101
				parse(offset < tokenTreshold ? tokenTreshold : offset);
102
 
103
			if(offset > (offset_type)m_right || (offset_type)m_left + offset < 0)
104
				setstate(failbit);
105
			else{
106
				m_left+=offset; m_right-=offset;
107
				if(m_right==0) 
108
					parse(tokenTreshold);
109
 
110
				advance(m_pos, offset);
111
 
112
				if(m_pos==m_end) 
113
					setstate(eofbit);
114
				else
115
					clear((state)(rdstate() & ~eofbit));
116
			}
117
			if(m_left > tokenUnloadTreshold)
118
				unload(tokenTreshold);
119
			return good();
120
		}
121
 
122
		token* previous()
123
		{
124
			if(m_left==0)
125
				return 0;
114 cycrow 126
			else{
127
				iterator it=m_pos;
128
				return *(--it);
129
			}
1 cycrow 130
		}
131
};
132
 
133
#endif // !defined(TOKEN_STREAM_INCLUDED)