Root/
Source at commit 1322 created 12 years 8 months ago. By meklort, Add doxygen to utils folder | |
---|---|
1 | /******************************************************************************␊ |
2 | *␊ |
3 | * $Id: basehandler.h,v 1.33 2002/10/13 21:01:58 dimitri Exp $␊ |
4 | *␊ |
5 | *␊ |
6 | * Copyright (C) 1997-2006 by Dimitri van Heesch.␊ |
7 | *␊ |
8 | * Permission to use, copy, modify, and distribute this software and its␊ |
9 | * documentation under the terms of the GNU General Public License is hereby ␊ |
10 | * granted. No representations are made about the suitability of this software ␊ |
11 | * for any purpose. It is provided "as is" without express or implied warranty.␊ |
12 | * See the GNU General Public License for more details.␊ |
13 | *␊ |
14 | */␊ |
15 | ␊ |
16 | #ifndef _BASEHANDLER_H␊ |
17 | #define _BASEHANDLER_H␊ |
18 | ␊ |
19 | #include <qxml.h>␊ |
20 | #include <qdict.h>␊ |
21 | #include <qstring.h>␊ |
22 | ␊ |
23 | #include "debug.h"␊ |
24 | ␊ |
25 | //-----------------------------------------------------------------------------␊ |
26 | ␊ |
27 | class IBaseHandler␊ |
28 | {␊ |
29 | public:␊ |
30 | virtual void setDelegate(QXmlDefaultHandler *delegate) = 0;␊ |
31 | virtual QXmlDefaultHandler *delegate() const = 0;␊ |
32 | virtual ~IBaseHandler() {}␊ |
33 | };␊ |
34 | ␊ |
35 | //-----------------------------------------------------------------------------␊ |
36 | ␊ |
37 | class IFallBackHandler␊ |
38 | {␊ |
39 | public:␊ |
40 | virtual bool handleStartElement(const QString & name, ␊ |
41 | const QXmlAttributes & attrib) = 0;␊ |
42 | virtual bool handleEndElement(const QString &name) = 0;␊ |
43 | virtual ~IFallBackHandler() {}␊ |
44 | };␊ |
45 | ␊ |
46 | //-----------------------------------------------------------------------------␊ |
47 | ␊ |
48 | template<class T> class ElementMapper␊ |
49 | {␊ |
50 | class StartElementHandler␊ |
51 | {␊ |
52 | typedef void (T::*Handler)(const QXmlAttributes &attrib);␊ |
53 | public:␊ |
54 | StartElementHandler() : m_parent(0) {}␊ |
55 | StartElementHandler(T *parent, Handler h) ␊ |
56 | : m_parent(parent), m_handler(h) {}␊ |
57 | void operator()(const QXmlAttributes &attrib) ␊ |
58 | { if (m_parent) (m_parent->*m_handler)(attrib); }␊ |
59 | private:␊ |
60 | T *m_parent;␊ |
61 | Handler m_handler;␊ |
62 | };␊ |
63 | ␊ |
64 | class EndElementHandler␊ |
65 | {␊ |
66 | typedef void (T::*Handler)();␊ |
67 | public:␊ |
68 | EndElementHandler() : m_parent(0) {}␊ |
69 | EndElementHandler(T *parent, Handler h) ␊ |
70 | : m_parent(parent), m_handler(h) {}␊ |
71 | void operator()() ␊ |
72 | { if (m_parent) (m_parent->*m_handler)(); }␊ |
73 | private:␊ |
74 | T *m_parent;␊ |
75 | Handler m_handler;␊ |
76 | };␊ |
77 | ␊ |
78 | public:␊ |
79 | typedef StartElementHandler StartElementHandlerT;␊ |
80 | typedef EndElementHandler EndElementHandlerT;␊ |
81 | ␉ ␊ |
82 | ␉ElementMapper() : m_startHandlers(67), m_endHandlers(67)␊ |
83 | {␊ |
84 | m_startHandlers.setAutoDelete(TRUE);␊ |
85 | m_endHandlers.setAutoDelete(TRUE);␊ |
86 | }␊ |
87 | virtual ~ElementMapper()␊ |
88 | {␊ |
89 | }␊ |
90 | ␊ |
91 | void addStartHandler(const char *key)␊ |
92 | {␊ |
93 | m_startHandlers.insert(key,new StartElementHandlerT);␊ |
94 | }␊ |
95 | ␊ |
96 | void addStartHandler(const char *key, T *obj, void (T::*handler)(const QXmlAttributes &))␊ |
97 | {␊ |
98 | m_startHandlers.insert(key,new StartElementHandlerT(obj,handler));␊ |
99 | }␊ |
100 | ␊ |
101 | void addEndHandler(const char *key)␊ |
102 | {␊ |
103 | m_endHandlers.insert(key,new EndElementHandlerT);␊ |
104 | }␊ |
105 | ␊ |
106 | void addEndHandler(const char *key, T *obj, void (T::*handler)())␊ |
107 | {␊ |
108 | m_endHandlers.insert(key,new EndElementHandlerT(obj,handler));␊ |
109 | }␊ |
110 | ␊ |
111 | ␊ |
112 | protected:␊ |
113 | QDict<StartElementHandlerT> m_startHandlers;␊ |
114 | QDict<EndElementHandlerT> m_endHandlers;␊ |
115 | };␊ |
116 | ␊ |
117 | //-----------------------------------------------------------------------------␊ |
118 | ␊ |
119 | struct LocatorContainer␊ |
120 | {␊ |
121 | static QXmlLocator *s_theLocator;␊ |
122 | };␊ |
123 | ␊ |
124 | //-----------------------------------------------------------------------------␊ |
125 | ␊ |
126 | template<class T> class BaseHandler : public QXmlDefaultHandler,␊ |
127 | public ElementMapper<T>,␊ |
128 | public LocatorContainer,␊ |
129 | public IBaseHandler␊ |
130 | {␊ |
131 | public:␊ |
132 | typedef typename ElementMapper<T>::StartElementHandlerT StartElementHandlerT;␊ |
133 | typedef typename ElementMapper<T>::EndElementHandlerT EndElementHandlerT;␊ |
134 | ␊ |
135 | BaseHandler() : m_delegateHandler(0), m_fallBackHandler(0)␊ |
136 | {␊ |
137 | }␊ |
138 | ␊ |
139 | virtual ~BaseHandler() ␊ |
140 | {␊ |
141 | ASSERT(m_delegateHandler==0);␊ |
142 | }␊ |
143 | ␊ |
144 | virtual bool startDocument() ␊ |
145 | {␊ |
146 | return TRUE;␊ |
147 | }␊ |
148 | ␊ |
149 | virtual bool startElement( const QString & namespaceURI, ␊ |
150 | const QString & localName, ␊ |
151 | const QString & name, ␊ |
152 | const QXmlAttributes & attrib␊ |
153 | )␊ |
154 | {␊ |
155 | if (m_delegateHandler) ␊ |
156 | {␊ |
157 | return m_delegateHandler->startElement(namespaceURI,localName,name,attrib);␊ |
158 | }␊ |
159 | if (!m_skipUntil.isEmpty()) // skip mode ␊ |
160 | {␊ |
161 | if (m_skipUntil==name) m_skipCount++;␊ |
162 | debug(1,"line %d, col %d: skipping start tag %s count=%d\n",␊ |
163 | s_theLocator->lineNumber(),s_theLocator->columnNumber(),␊ |
164 | name.data(),m_skipCount);␊ |
165 | return TRUE; ␊ |
166 | }␊ |
167 | ␊ |
168 | StartElementHandlerT *handler = ElementMapper<T>::m_startHandlers[name];␊ |
169 | if (handler)␊ |
170 | {␊ |
171 | (*handler)(attrib);␊ |
172 | //printf("found start tag %s\n",name.data());␊ |
173 | }␊ |
174 | else if (!m_fallBackHandler ||␊ |
175 | !m_fallBackHandler->handleStartElement(name,attrib)␊ |
176 | )␊ |
177 | {␊ |
178 | debug(1,"line %d, col %d: found unexpected tag `%s', skipping until matching end tag\n",␊ |
179 | s_theLocator->lineNumber(),s_theLocator->columnNumber(),␊ |
180 | name.data());␊ |
181 | m_skipUntil = name;␊ |
182 | m_skipCount=1;␊ |
183 | }␊ |
184 | return TRUE;␊ |
185 | }␊ |
186 | ␊ |
187 | virtual bool endElement( const QString& namespaceURI, const QString& localName, const QString& name )␊ |
188 | {␊ |
189 | if (m_delegateHandler) ␊ |
190 | {␊ |
191 | return m_delegateHandler->endElement(namespaceURI,localName,name);␊ |
192 | }␊ |
193 | ␊ |
194 | if (name==m_skipUntil)␊ |
195 | {␊ |
196 | m_skipCount--;␊ |
197 | debug(1,"line %d, col %d: skipping end tag %s count=%d\n",␊ |
198 | s_theLocator->lineNumber(),s_theLocator->columnNumber(),␊ |
199 | name.data(),m_skipCount);␊ |
200 | if (m_skipCount==0)␊ |
201 | {␊ |
202 | m_skipUntil="";␊ |
203 | }␊ |
204 | //printf("found end tag %s\n",name.data());␊ |
205 | }␊ |
206 | else if (m_skipUntil.isEmpty())␊ |
207 | {␊ |
208 | EndElementHandlerT *handler = ElementMapper<T>::m_endHandlers[name];␊ |
209 | if (handler)␊ |
210 | {␊ |
211 | (*handler)();␊ |
212 | //printf("found end tag %s\n",name.data());␊ |
213 | }␊ |
214 | else if (m_fallBackHandler)␊ |
215 | {␊ |
216 | m_fallBackHandler->handleEndElement(name);␊ |
217 | }␊ |
218 | }␊ |
219 | m_curString="";␊ |
220 | return TRUE;␊ |
221 | }␊ |
222 | ␊ |
223 | bool skippedEntity ( const QString &s )␊ |
224 | {␊ |
225 | if (m_delegateHandler)␊ |
226 | {␊ |
227 | return m_delegateHandler->skippedEntity(s);␊ |
228 | }␊ |
229 | ␊ |
230 | debug(1,"line %d, col %d: Skipped unhandled entity %s\n",␊ |
231 | s_theLocator->lineNumber(),s_theLocator->columnNumber(),␊ |
232 | s.data());␊ |
233 | return TRUE;␊ |
234 | }␊ |
235 | ␊ |
236 | /*! called when a number of characters are received by the parser.␊ |
237 | * \param ch the characters.␊ |
238 | */␊ |
239 | virtual bool characters ( const QString & ch ) ␊ |
240 | {␊ |
241 | if (m_delegateHandler) ␊ |
242 | {␊ |
243 | return m_delegateHandler->characters(ch);␊ |
244 | }␊ |
245 | ␊ |
246 | //printf("Found characters \"%s\"\n",ch.data());␊ |
247 | m_curString+=ch;␊ |
248 | return TRUE;␊ |
249 | }␊ |
250 | ␊ |
251 | void setDelegate(QXmlDefaultHandler *delegate)␊ |
252 | {␊ |
253 | m_delegateHandler = delegate;␊ |
254 | }␊ |
255 | ␊ |
256 | QXmlDefaultHandler *delegate() const␊ |
257 | {␊ |
258 | return m_delegateHandler;␊ |
259 | }␊ |
260 | ␊ |
261 | void setFallBackHandler(IFallBackHandler *h)␊ |
262 | {␊ |
263 | m_fallBackHandler = h;␊ |
264 | }␊ |
265 | ␊ |
266 | IFallBackHandler *fallBackHandler() const␊ |
267 | {␊ |
268 | return m_fallBackHandler;␊ |
269 | }␊ |
270 | ␊ |
271 | void setDocumentLocator( QXmlLocator * locator )␊ |
272 | {␊ |
273 | debug(2,"setDocumentLocator(%p)\n",locator);␊ |
274 | s_theLocator = locator;␊ |
275 | }␊ |
276 | ␊ |
277 | protected:␊ |
278 | QString m_curString;␊ |
279 | QString m_skipUntil;␊ |
280 | int m_skipCount;␊ |
281 | QXmlDefaultHandler *m_delegateHandler;␊ |
282 | IFallBackHandler *m_fallBackHandler;␊ |
283 | };␊ |
284 | ␊ |
285 | //-----------------------------------------------------------------------------␊ |
286 | ␊ |
287 | template<class T> class BaseFallBackHandler : public ElementMapper<T>,␊ |
288 | public IFallBackHandler␊ |
289 | {␊ |
290 | public:␊ |
291 | typedef typename ElementMapper<T>::StartElementHandlerT StartElementHandlerT;␊ |
292 | typedef typename ElementMapper<T>::EndElementHandlerT EndElementHandlerT;␊ |
293 | ␊ |
294 | BaseFallBackHandler() ␊ |
295 | {␊ |
296 | }␊ |
297 | virtual ~BaseFallBackHandler()␊ |
298 | {␊ |
299 | }␊ |
300 | ␊ |
301 | bool handleStartElement(const QString & name, ␊ |
302 | const QXmlAttributes & attrib)␊ |
303 | {␊ |
304 | StartElementHandlerT *handler = ElementMapper<T>::m_startHandlers[name];␊ |
305 | if (handler)␊ |
306 | {␊ |
307 | (*handler)(attrib);␊ |
308 | return TRUE;␊ |
309 | }␊ |
310 | return FALSE;␊ |
311 | }␊ |
312 | bool handleEndElement(const QString &name)␊ |
313 | {␊ |
314 | EndElementHandlerT *handler = ElementMapper<T>::m_endHandlers[name];␊ |
315 | if (handler)␊ |
316 | {␊ |
317 | (*handler)();␊ |
318 | return TRUE;␊ |
319 | }␊ |
320 | return FALSE;␊ |
321 | }␊ |
322 | };␊ |
323 | ␊ |
324 | ␊ |
325 | #endif␊ |
326 |