|
Packit |
1c1d7e |
/******************************************************************************
|
|
Packit |
1c1d7e |
*
|
|
Packit |
1c1d7e |
* $Id$
|
|
Packit |
1c1d7e |
*
|
|
Packit |
1c1d7e |
*
|
|
Packit |
1c1d7e |
* Copyright (C) 1997-2015 by Dimitri van Heesch.
|
|
Packit |
1c1d7e |
*
|
|
Packit |
1c1d7e |
* Permission to use, copy, modify, and distribute this software and its
|
|
Packit |
1c1d7e |
* documentation under the terms of the GNU General Public License is hereby
|
|
Packit |
1c1d7e |
* granted. No representations are made about the suitability of this software
|
|
Packit |
1c1d7e |
* for any purpose. It is provided "as is" without express or implied warranty.
|
|
Packit |
1c1d7e |
* See the GNU General Public License for more details.
|
|
Packit |
1c1d7e |
*
|
|
Packit |
1c1d7e |
*/
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
#ifndef _BASEHANDLER_H
|
|
Packit |
1c1d7e |
#define _BASEHANDLER_H
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
#include <qxml.h>
|
|
Packit |
1c1d7e |
#include <qdict.h>
|
|
Packit |
1c1d7e |
#include <qstring.h>
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
#include "debug.h"
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
//-----------------------------------------------------------------------------
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
class IBaseHandler
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
public:
|
|
Packit |
1c1d7e |
virtual void setDelegate(QXmlDefaultHandler *delegate) = 0;
|
|
Packit |
1c1d7e |
virtual QXmlDefaultHandler *delegate() const = 0;
|
|
Packit |
1c1d7e |
virtual ~IBaseHandler() {}
|
|
Packit |
1c1d7e |
};
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
//-----------------------------------------------------------------------------
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
class IFallBackHandler
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
public:
|
|
Packit |
1c1d7e |
virtual bool handleStartElement(const QString & name,
|
|
Packit |
1c1d7e |
const QXmlAttributes & attrib) = 0;
|
|
Packit |
1c1d7e |
virtual bool handleEndElement(const QString &name) = 0;
|
|
Packit |
1c1d7e |
virtual ~IFallBackHandler() {}
|
|
Packit |
1c1d7e |
};
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
//-----------------------------------------------------------------------------
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
template<class T> class ElementMapper
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
class StartElementHandler
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
typedef void (T::*Handler)(const QXmlAttributes &attrib);
|
|
Packit |
1c1d7e |
public:
|
|
Packit |
1c1d7e |
StartElementHandler() : m_parent(0) {}
|
|
Packit |
1c1d7e |
StartElementHandler(T *parent, Handler h)
|
|
Packit |
1c1d7e |
: m_parent(parent), m_handler(h) {}
|
|
Packit |
1c1d7e |
void operator()(const QXmlAttributes &attrib)
|
|
Packit |
1c1d7e |
{ if (m_parent) (m_parent->*m_handler)(attrib); }
|
|
Packit |
1c1d7e |
private:
|
|
Packit |
1c1d7e |
T *m_parent;
|
|
Packit |
1c1d7e |
Handler m_handler;
|
|
Packit |
1c1d7e |
};
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
class EndElementHandler
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
typedef void (T::*Handler)();
|
|
Packit |
1c1d7e |
public:
|
|
Packit |
1c1d7e |
EndElementHandler() : m_parent(0) {}
|
|
Packit |
1c1d7e |
EndElementHandler(T *parent, Handler h)
|
|
Packit |
1c1d7e |
: m_parent(parent), m_handler(h) {}
|
|
Packit |
1c1d7e |
void operator()()
|
|
Packit |
1c1d7e |
{ if (m_parent) (m_parent->*m_handler)(); }
|
|
Packit |
1c1d7e |
private:
|
|
Packit |
1c1d7e |
T *m_parent;
|
|
Packit |
1c1d7e |
Handler m_handler;
|
|
Packit |
1c1d7e |
};
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
public:
|
|
Packit |
1c1d7e |
typedef StartElementHandler StartElementHandlerT;
|
|
Packit |
1c1d7e |
typedef EndElementHandler EndElementHandlerT;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
ElementMapper() : m_startHandlers(67), m_endHandlers(67)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
m_startHandlers.setAutoDelete(TRUE);
|
|
Packit |
1c1d7e |
m_endHandlers.setAutoDelete(TRUE);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
virtual ~ElementMapper()
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
void addStartHandler(const char *key)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
m_startHandlers.insert(key,new StartElementHandlerT);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
void addStartHandler(const char *key, T *obj, void (T::*handler)(const QXmlAttributes &))
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
m_startHandlers.insert(key,new StartElementHandlerT(obj,handler));
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
void addEndHandler(const char *key)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
m_endHandlers.insert(key,new EndElementHandlerT);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
void addEndHandler(const char *key, T *obj, void (T::*handler)())
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
m_endHandlers.insert(key,new EndElementHandlerT(obj,handler));
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
protected:
|
|
Packit |
1c1d7e |
QDict<StartElementHandlerT> m_startHandlers;
|
|
Packit |
1c1d7e |
QDict<EndElementHandlerT> m_endHandlers;
|
|
Packit |
1c1d7e |
};
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
//-----------------------------------------------------------------------------
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
struct LocatorContainer
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
static QXmlLocator *s_theLocator;
|
|
Packit |
1c1d7e |
};
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
//-----------------------------------------------------------------------------
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
template<class T> class BaseHandler : public QXmlDefaultHandler,
|
|
Packit |
1c1d7e |
public ElementMapper<T>,
|
|
Packit |
1c1d7e |
public LocatorContainer,
|
|
Packit |
1c1d7e |
public IBaseHandler
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
public:
|
|
Packit |
1c1d7e |
typedef typename ElementMapper<T>::StartElementHandlerT StartElementHandlerT;
|
|
Packit |
1c1d7e |
typedef typename ElementMapper<T>::EndElementHandlerT EndElementHandlerT;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
BaseHandler() : m_skipCount(0), m_delegateHandler(0), m_fallBackHandler(0)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
virtual ~BaseHandler()
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
ASSERT(m_delegateHandler==0);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
virtual bool startDocument()
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
return TRUE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
virtual bool startElement( const QString & namespaceURI,
|
|
Packit |
1c1d7e |
const QString & localName,
|
|
Packit |
1c1d7e |
const QString & name,
|
|
Packit |
1c1d7e |
const QXmlAttributes & attrib
|
|
Packit |
1c1d7e |
)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (m_delegateHandler)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
return m_delegateHandler->startElement(namespaceURI,localName,name,attrib);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
if (!m_skipUntil.isEmpty()) // skip mode
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (m_skipUntil==name) m_skipCount++;
|
|
Packit |
1c1d7e |
debug(1,"line %d, col %d: skipping start tag %s count=%d\n",
|
|
Packit |
1c1d7e |
s_theLocator->lineNumber(),s_theLocator->columnNumber(),
|
|
Packit |
1c1d7e |
name.data(),m_skipCount);
|
|
Packit |
1c1d7e |
return TRUE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
StartElementHandlerT *handler = ElementMapper<T>::m_startHandlers[name.utf8()];
|
|
Packit |
1c1d7e |
if (handler)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
(*handler)(attrib);
|
|
Packit |
1c1d7e |
//printf("found start tag %s\n",name.data());
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else if (!m_fallBackHandler ||
|
|
Packit |
1c1d7e |
!m_fallBackHandler->handleStartElement(name,attrib)
|
|
Packit |
1c1d7e |
)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
debug(1,"line %d, col %d: found unexpected tag `%s', skipping until matching end tag\n",
|
|
Packit |
1c1d7e |
s_theLocator->lineNumber(),s_theLocator->columnNumber(),
|
|
Packit |
1c1d7e |
name.data());
|
|
Packit |
1c1d7e |
m_skipUntil = name;
|
|
Packit |
1c1d7e |
m_skipCount=1;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
return TRUE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
virtual bool endElement( const QString& namespaceURI, const QString& localName, const QString& name )
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (m_delegateHandler)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
return m_delegateHandler->endElement(namespaceURI,localName,name);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
if (name==m_skipUntil)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
m_skipCount--;
|
|
Packit |
1c1d7e |
debug(1,"line %d, col %d: skipping end tag %s count=%d\n",
|
|
Packit |
1c1d7e |
s_theLocator->lineNumber(),s_theLocator->columnNumber(),
|
|
Packit |
1c1d7e |
name.data(),m_skipCount);
|
|
Packit |
1c1d7e |
if (m_skipCount==0)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
m_skipUntil="";
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
//printf("found end tag %s\n",name.data());
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else if (m_skipUntil.isEmpty())
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
EndElementHandlerT *handler = ElementMapper<T>::m_endHandlers[name.utf8()];
|
|
Packit |
1c1d7e |
if (handler)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
(*handler)();
|
|
Packit |
1c1d7e |
//printf("found end tag %s\n",name.data());
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else if (m_fallBackHandler)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
m_fallBackHandler->handleEndElement(name);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
m_curString="";
|
|
Packit |
1c1d7e |
return TRUE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
bool skippedEntity ( const QString &s )
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (m_delegateHandler)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
return m_delegateHandler->skippedEntity(s);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
debug(1,"line %d, col %d: Skipped unhandled entity %s\n",
|
|
Packit |
1c1d7e |
s_theLocator->lineNumber(),s_theLocator->columnNumber(),
|
|
Packit |
1c1d7e |
s.data());
|
|
Packit |
1c1d7e |
return TRUE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/*! called when a number of characters are received by the parser.
|
|
Packit |
1c1d7e |
* \param ch the characters.
|
|
Packit |
1c1d7e |
*/
|
|
Packit |
1c1d7e |
virtual bool characters ( const QString & ch )
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (m_delegateHandler)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
return m_delegateHandler->characters(ch);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
//printf("Found characters \"%s\"\n",ch.data());
|
|
Packit |
1c1d7e |
m_curString+=ch;
|
|
Packit |
1c1d7e |
return TRUE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
void setDelegate(QXmlDefaultHandler *delegate)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
m_delegateHandler = delegate;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
QXmlDefaultHandler *delegate() const
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
return m_delegateHandler;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
void setFallBackHandler(IFallBackHandler *h)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
m_fallBackHandler = h;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
IFallBackHandler *fallBackHandler() const
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
return m_fallBackHandler;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
void setDocumentLocator( QXmlLocator * locator )
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
debug(2,"setDocumentLocator(%p)\n",locator);
|
|
Packit |
1c1d7e |
s_theLocator = locator;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
protected:
|
|
Packit |
1c1d7e |
QString m_curString;
|
|
Packit |
1c1d7e |
QString m_skipUntil;
|
|
Packit |
1c1d7e |
int m_skipCount;
|
|
Packit |
1c1d7e |
QXmlDefaultHandler *m_delegateHandler;
|
|
Packit |
1c1d7e |
IFallBackHandler *m_fallBackHandler;
|
|
Packit |
1c1d7e |
};
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
//-----------------------------------------------------------------------------
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
template<class T> class BaseFallBackHandler : public ElementMapper<T>,
|
|
Packit |
1c1d7e |
public IFallBackHandler
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
public:
|
|
Packit |
1c1d7e |
typedef typename ElementMapper<T>::StartElementHandlerT StartElementHandlerT;
|
|
Packit |
1c1d7e |
typedef typename ElementMapper<T>::EndElementHandlerT EndElementHandlerT;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
BaseFallBackHandler()
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
virtual ~BaseFallBackHandler()
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
bool handleStartElement(const QString & name,
|
|
Packit |
1c1d7e |
const QXmlAttributes & attrib)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
StartElementHandlerT *handler = ElementMapper<T>::m_startHandlers[name.utf8()];
|
|
Packit |
1c1d7e |
if (handler)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
(*handler)(attrib);
|
|
Packit |
1c1d7e |
return TRUE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
return FALSE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
bool handleEndElement(const QString &name)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
EndElementHandlerT *handler = ElementMapper<T>::m_endHandlers[name.utf8()];
|
|
Packit |
1c1d7e |
if (handler)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
(*handler)();
|
|
Packit |
1c1d7e |
return TRUE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
return FALSE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
};
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
#endif
|