diff --git a/build.sh b/build.sh index f80276df6..361aeda9b 100755 --- a/build.sh +++ b/build.sh @@ -27,6 +27,7 @@ HAVE_QTBINDINGS=1 HAVE_64BIT_COORD=0 HAVE_QT5="" HAVE_CURL="" +HAVE_EXPAT="" RUBYINCLUDE="" RUBYINCLUDE2="" @@ -157,6 +158,9 @@ while [ "$*" != "" ]; do -libcurl) HAVE_CURL=1 ;; + -libexpat) + HAVE_EXPAT=1 + ;; -option) MAKE_OPT="$MAKE_OPT $1" shift @@ -203,7 +207,8 @@ while [ "$*" != "" ]; do echo " -pylib Location of the .so/.dll to link for Python support" echo " -pyinc Location of the Python headers (in particular 'Python.h')" echo "" - echo " -libcurl Use libcurl instead of QNetwork (for Qt<4.7)" + echo " -libcurl Use libcurl instead of QtNetwork (for Qt<4.7)" + echo " -libexpat Use libexpat instead of QtXml" echo "" exit 0 ;; @@ -547,6 +552,7 @@ qmake_options=( HAVE_64BIT_COORD="$HAVE_64BIT_COORD" HAVE_QT5="$HAVE_QT5" HAVE_CURL="$HAVE_CURL" + HAVE_EXPAT="$HAVE_EXPAT" PREFIX="$BIN" RPATH="$RPATH" KLAYOUT_VERSION="$KLAYOUT_VERSION" diff --git a/src/klayout.pri b/src/klayout.pri index 0316acfeb..fc53c5dbe 100644 --- a/src/klayout.pri +++ b/src/klayout.pri @@ -47,6 +47,10 @@ equals(HAVE_CURL, "1") { DEFINES += HAVE_CURL } +equals(HAVE_EXPAT, "1") { + DEFINES += HAVE_EXPAT +} + equals(HAVE_RUBY, "1") { DEFINES += \ HAVE_RUBY \ diff --git a/src/rdb/rdb/rdbFile.cc b/src/rdb/rdb/rdbFile.cc index efccad8c8..757685862 100644 --- a/src/rdb/rdb/rdbFile.cc +++ b/src/rdb/rdb/rdbFile.cc @@ -106,7 +106,9 @@ make_rdb_structure (rdb::Database *rdb) tl::make_member (&rdb::Item::cell_qname, &rdb::Item::set_cell_qname, "cell") + tl::make_member (&rdb::Item::visited, &rdb::Item::set_visited, "visited") + tl::make_member (&rdb::Item::multiplicity, &rdb::Item::set_multiplicity, "multiplicity") + +#if defined(HAVE_QT) tl::make_member (&rdb::Item::image_str, &rdb::Item::set_image_str, "image") + +#endif tl::make_element (&rdb::Item::values, &rdb::Item::set_values, "values", tl::make_member (&rdb::Values::begin, &rdb::Values::end, &rdb::Values::add, "value", ValueConverter (rdb)) ) @@ -145,7 +147,7 @@ public: virtual void read (Database &db) { tl::SelfTimer timer (tl::verbosity () >= 11, "Reading marker database file"); - tl::XMLStreamSource in (m_input_stream, tl::to_string (QObject::tr ("Reading RDB"))); + tl::XMLStreamSource in (m_input_stream, tl::to_string (tr ("Reading RDB"))); make_rdb_structure (&db).parse (in, db); } diff --git a/src/rdb/unit_tests/rdb.cc b/src/rdb/unit_tests/rdb.cc index 3059a5be2..1905d90f9 100644 --- a/src/rdb/unit_tests/rdb.cc +++ b/src/rdb/unit_tests/rdb.cc @@ -27,8 +27,6 @@ #include "dbBox.h" #include "dbEdge.h" -#include - TEST(1) { rdb::Database db; diff --git a/src/tl/tl/tl.pro b/src/tl/tl/tl.pro index 48590562a..46c85391d 100644 --- a/src/tl/tl/tl.pro +++ b/src/tl/tl/tl.pro @@ -44,6 +44,8 @@ SOURCES = \ tlCommandLineParser.cc \ tlUnitTest.cc \ tlInt128Support.cc \ + tlXMLParser.cc \ + tlXMLWriter.cc \ tlThreadedWorkers.cc \ tlThreads.cc @@ -91,46 +93,44 @@ HEADERS = \ tlInt128Support.h \ tlHttpStreamCurl.h \ tlDefs.h \ + tlXMLParser.h \ + tlXMLWriter.h \ tlThreadedWorkers.h \ tlThreads.h equals(HAVE_CURL, "1") { + HEADERS += \ + tlWebDAV.h \ + SOURCES += \ tlHttpStreamCurl.cc \ + tlWebDAV.cc \ } else { - equals(HAVE_QT, "0") { - # no HTTP stream available - } else { + !equals(HAVE_QT, "0") { + + HEADERS += \ + tlHttpStreamQt.h \ + tlWebDAV.h \ SOURCES += \ tlHttpStreamQt.cc \ + tlWebDAV.cc \ } } -equals(HAVE_QT, "0") { - - # nothing - -} else { +!equals(HAVE_QT, "0") { HEADERS += \ - tlWebDAV.h \ tlDeferredExecution.h \ - tlXMLParser.h \ - tlXMLWriter.h \ tlFileSystemWatcher.h \ - tlHttpStreamQt.h \ SOURCES += \ - tlWebDAV.cc \ tlDeferredExecution.cc \ - tlXMLParser.cc \ - tlXMLWriter.cc \ tlFileSystemWatcher.cc \ } diff --git a/src/tl/tl/tlXMLParser.cc b/src/tl/tl/tlXMLParser.cc index 6ac981bd6..a4fe81f93 100644 --- a/src/tl/tl/tlXMLParser.cc +++ b/src/tl/tl/tlXMLParser.cc @@ -27,29 +27,484 @@ #include "tlAssert.h" #include "tlProgress.h" -#include -#include - #include +#include + +#if defined(HAVE_EXPAT) + +#include namespace tl { +// -------------------------------------------------------------------- +// SourcePrivateData implementation + +class XMLSourcePrivateData +{ +public: + XMLSourcePrivateData (tl::InputStreamBase *stream_delegate) + : mp_stream_holder (new tl::InputStream (*stream_delegate)), + mp_stream_delegate (stream_delegate), + m_has_error (false) + { + mp_stream = mp_stream_holder.get (); + } + + XMLSourcePrivateData (tl::InputStreamBase *stream_delegate, const std::string &progress_message) + : mp_stream_holder (new tl::InputStream (*stream_delegate)), + mp_stream_delegate (stream_delegate), + mp_progress (new AbsoluteProgress (progress_message, 100)), + m_has_error (false) + { + mp_stream = mp_stream_holder.get (); + mp_progress->set_format (tl::to_string (tr ("%.0f MB"))); + mp_progress->set_unit (1024 * 1024); + } + + XMLSourcePrivateData (tl::InputStream &stream) + : m_has_error (false) + { + mp_stream = &stream; + } + + XMLSourcePrivateData (tl::InputStream &stream, const std::string &progress_message) + : mp_progress (new AbsoluteProgress (progress_message, 100)), + m_has_error (false) + { + mp_stream = &stream; + mp_progress->set_format (tl::to_string (tr ("%.0f MB"))); + mp_progress->set_unit (1024 * 1024); + } + + size_t read (char *data, size_t n) + { + try { + + if (mp_progress.get ()) { + mp_progress->set (mp_stream->pos ()); + } + + size_t n0 = n; + for (const char *rd = 0; n > 0 && (rd = mp_stream->get (1)) != 0; --n) { + *data++ = *rd; + } + + if (n0 == n) { + return -1; + } else { + return n0 - n; + } + + } catch (tl::Exception &ex) { + m_error = ex.msg (); + m_has_error = true; + return -1; + } + } + + bool has_error () const + { + return m_has_error; + } + + const std::string &error_msg () const + { + return m_error; + } + +private: + std::auto_ptr mp_stream_holder; + tl::InputStream *mp_stream; + std::auto_ptr mp_stream_delegate; + std::auto_ptr mp_progress; + bool m_has_error; + std::string m_error; +}; + +// -------------------------------------------------------------------- +// XMLSource implementation + +XMLSource::XMLSource () + : mp_source (0) +{ + // .. nothing yet .. +} + +XMLSource::~XMLSource () +{ + delete mp_source; + mp_source = 0; +} + // -------------------------------------------------------------------- // XMLStringSource implementation XMLStringSource::XMLStringSource (const std::string &string) { - mp_source = new QXmlInputSource (); - mp_source->setData (QByteArray (string.c_str ())); + set_source (new XMLSourcePrivateData (new tl::InputMemoryStream (string.c_str (), string.size ()))); } XMLStringSource::~XMLStringSource () +{ + // .. nothing yet .. +} + +// -------------------------------------------------------------------- +// XMLFileSource implementation + +XMLFileSource::XMLFileSource (const std::string &path, const std::string &progress_message) +{ + set_source (new XMLSourcePrivateData (new tl::InputZLibFile (path), progress_message)); +} + +XMLFileSource::XMLFileSource (const std::string &path) +{ + set_source (new XMLSourcePrivateData (new tl::InputZLibFile (path))); +} + +XMLFileSource::~XMLFileSource () +{ + // .. nothing yet .. +} + +// -------------------------------------------------------------------- +// XMLStreamSource implementation + +XMLStreamSource::XMLStreamSource (tl::InputStream &s, const std::string &progress_message) +{ + set_source (new XMLSourcePrivateData (s, progress_message)); +} + +XMLStreamSource::XMLStreamSource (tl::InputStream &s) +{ + set_source (new XMLSourcePrivateData (s)); +} + +XMLStreamSource::~XMLStreamSource () +{ + // .. nothing yet .. +} + +// -------------------------------------------------------------------- +// XMLParser implementation + +void XMLCALL start_element_handler (void *user_data, const XML_Char *name, const XML_Char **atts); +void XMLCALL end_element_handler (void *user_data, const XML_Char *name); +void XMLCALL cdata_handler (void *user_data, const XML_Char *s, int len); + +class XMLParserPrivateData +{ +public: + XMLParserPrivateData () + : mp_struct_handler (0) + { + mp_parser = XML_ParserCreate ("UTF-8"); + tl_assert (mp_parser != NULL); + XML_SetUserData (mp_parser, (void *) this); + XML_SetElementHandler (mp_parser, start_element_handler, end_element_handler); + XML_SetCharacterDataHandler (mp_parser, cdata_handler); + } + + ~XMLParserPrivateData () + { + if (mp_parser != NULL) { + XML_ParserFree (mp_parser); + } + } + + void start_element (const std::string &name) + { + try { + // TODO: separate qname and lname? + mp_struct_handler->start_element (std::string (), name, name); + } catch (tl::Exception &ex) { + error (ex); + } + } + + void end_element (const std::string &name) + { + try { + // TODO: separate qname and lname? + mp_struct_handler->end_element (std::string (), name, name); + } catch (tl::Exception &ex) { + error (ex); + } + } + + void cdata (const std::string &cdata) + { + try { + mp_struct_handler->characters (cdata); + } catch (tl::Exception &ex) { + error (ex); + } + } + + void parse (tl::XMLSource &source, XMLStructureHandler &struct_handler) + { + m_has_error = false; + mp_struct_handler = &struct_handler; + + // Just in case we want to reuse it ... + XML_ParserReset (mp_parser, "UTF-8"); + + const size_t chunk = 65536; + char buffer [chunk]; + + size_t n; + + do { + + try { + + n = source.source ()->read (buffer, chunk); + + XML_Status status = XML_Parse (mp_parser, buffer, int (n), n < chunk /*is final*/); + if (status == XML_STATUS_ERROR) { + m_has_error = true; + m_error = XML_ErrorString (XML_GetErrorCode (mp_parser)); + m_error_line = XML_GetErrorLineNumber (mp_parser); + m_error_column = XML_GetErrorColumnNumber (mp_parser); + } + + } catch (tl::Exception &ex) { + error (ex); + } + + } while (n == chunk && !m_has_error); + } + + void check_error () + { + if (m_has_error) { + throw tl::XMLLocatedException (m_error, m_error_line, m_error_column); + } + } + +private: + void error (tl::Exception &ex) + { + m_has_error = true; + m_error_line = XML_GetCurrentLineNumber (mp_parser); + m_error_column = XML_GetCurrentColumnNumber (mp_parser); + m_error = ex.msg (); + } + + XML_Parser mp_parser; + XMLStructureHandler *mp_struct_handler; + bool m_has_error; + std::string m_error; + int m_error_line, m_error_column; +}; + +void start_element_handler (void *user_data, const XML_Char *name, const XML_Char ** /*atts*/) +{ + XMLParserPrivateData *d = reinterpret_cast (user_data); + d->start_element (std::string (name)); +} + +void end_element_handler (void *user_data, const XML_Char *name) +{ + XMLParserPrivateData *d = reinterpret_cast (user_data); + d->end_element (std::string (name)); +} + +void cdata_handler (void *user_data, const XML_Char *s, int len) +{ + XMLParserPrivateData *d = reinterpret_cast (user_data); + d->cdata (std::string (s, 0, size_t (len))); +} + + +XMLParser::XMLParser () + : mp_data (new XMLParserPrivateData ()) +{ + // .. nothing yet .. +} + +XMLParser::~XMLParser () +{ + delete mp_data; + mp_data = 0; +} + +void +XMLParser::parse (XMLSource &source, XMLStructureHandler &struct_handler) +{ + mp_data->parse (source, struct_handler); + + // throws an exception if there is an error + mp_data->check_error (); +} + +} + +#elif defined(HAVE_QT) + +#include +#include + +namespace tl +{ + +// -------------------------------------------------------------------- +// A SAX handler for the Qt implementation + +class SAXHandler + : public QXmlDefaultHandler +{ +public: + SAXHandler (trureHandler *sh); + + bool characters (const QString &ch); + bool endElement (const QString &namespaceURI, const QString &localName, const QString &qName); + bool startElement (const QString &namespaceURI, const QString &localName, const QString &qName, const QXmlAttributes &atts); + bool error (const QXmlParseException &exception); + bool fatalError (const QXmlParseException &exception); + bool warning (const QXmlParseException &exception); + + void setDocumentLocator (QXmlLocator *locator); + +private: + QXmlLocator *mp_locator; + trureHandler *mp_struct_handler; +}; + +// -------------------------------------------------------------------------------------------------------- +// trureHandler implementation + +SAXHandler::SAXHandler (trureHandler *sh) + : QXmlDefaultHandler (), mp_locator (0), mp_struct_handler (sh) +{ + // .. nothing yet .. +} + +void +SAXHandler::setDocumentLocator (QXmlLocator *locator) +{ + mp_locator = locator; +} + +bool +SAXHandler::startElement (const QString &qs_uri, const QString &qs_lname, const QString &qs_qname, const QXmlAttributes & /*atts*/) +{ + std::string uri (tl::to_string (qs_uri)); + std::string lname (tl::to_string (qs_lname)); + std::string qname (tl::to_string (qs_qname)); + + try { + mp_struct_handler->start_element (uri, lname, qname); + } catch (tl::XMLException &ex) { + throw tl::XMLLocatedException (ex.raw_msg (), mp_locator->lineNumber (), mp_locator->columnNumber ()); + } catch (tl::Exception &ex) { + throw tl::XMLLocatedException (ex.msg (), mp_locator->lineNumber (), mp_locator->columnNumber ()); + } + + // successful + return true; +} + +bool +SAXHandler::endElement (const QString &qs_uri, const QString &qs_lname, const QString &qs_qname) +{ + std::string uri (tl::to_string (qs_uri)); + std::string lname (tl::to_string (qs_lname)); + std::string qname (tl::to_string (qs_qname)); + + try { + mp_struct_handler->end_element (uri, lname, qname); + } catch (tl::XMLException &ex) { + throw tl::XMLLocatedException (ex.raw_msg (), mp_locator->lineNumber (), mp_locator->columnNumber ()); + } catch (tl::Exception &ex) { + throw tl::XMLLocatedException (ex.msg (), mp_locator->lineNumber (), mp_locator->columnNumber ()); + } + + // successful + return true; +} + +bool +SAXHandler::characters (const QString &t) +{ + try { + mp_struct_handler->cdata (tl::to_string (t)); + } catch (tl::XMLException &ex) { + throw tl::XMLLocatedException (ex.raw_msg (), mp_locator->lineNumber (), mp_locator->columnNumber ()); + } catch (tl::Exception &ex) { + throw tl::XMLLocatedException (ex.msg (), mp_locator->lineNumber (), mp_locator->columnNumber ()); + } + + // successful + return true; +} + +bool +SAXHandler::error (const QXmlParseException &ex) +{ + throw tl::XMLLocatedException (tl::to_string (ex.message ()), ex.lineNumber (), ex.columnNumber ()); +} + +bool +SAXHandler::fatalError (const QXmlParseException &ex) +{ + throw tl::XMLLocatedException (tl::to_string (ex.message ()), ex.lineNumber (), ex.columnNumber ()); +} + +bool +SAXHandler::warning (const QXmlParseException &ex) +{ + tl::XMLLocatedException lex (tl::to_string (ex.message ()), ex.lineNumber (), ex.columnNumber ()); + tl::warn << lex.msg (); + // continue + return true; +} + +// -------------------------------------------------------------------- +// SourcePrivateData implementation + +class XMLSourcePrivateData + : public QXmlInputSource +{ +public: + XMLSourcePrivateData () + : QXmlInputSource () + { + // .. nothing yet .. + } +}; + +// -------------------------------------------------------------------- +// XMLSource implementation + +XMLSource::XMLSource () + : mp_source (0) +{ + // .. nothing yet .. +} + +XMLSource::~XMLSource () { delete mp_source; mp_source = 0; } +// -------------------------------------------------------------------- +// XMLStringSource implementation + +XMLStringSource::XMLStringSource (const std::string &string) +{ + XMLSourcePrivateData *source = new XMLSourcePrivateData (); + source->setData (QByteArray (string.c_str ())); + set_source (source); +} + +XMLStringSource::~XMLStringSource () +{ + // .. nothing yet .. +} + // -------------------------------------------------------------------- // StreamIODevice definition and implementation @@ -70,7 +525,7 @@ public: mp_progress (new AbsoluteProgress (progress_message, 100)), m_has_error (false) { - mp_progress->set_format (tl::to_string (QObject::tr ("%.0f MB"))); + mp_progress->set_format (tl::to_string (tr ("%.0f MB"))); mp_progress->set_unit (1024 * 1024); open (QIODevice::ReadOnly); } @@ -131,14 +586,63 @@ private: }; // -------------------------------------------------------------------- -// ErrorAwareQXmlInputSource definition and implementation +// XMLFileSource implementation -class ErrorAwareQXmlInputSource - : public QXmlInputSource +class XMLFileSourcePrivateData + : public XMLSourcePrivateData { public: - ErrorAwareQXmlInputSource (StreamIODevice *dev) - : QXmlInputSource (dev), mp_dev (dev) + XMLFileSourcePrivateData (const std::string &path, const std::string &progress_message) + : m_stream (path) + { + mp_io.reset (new StreamIODevice (m_stream, progress_message)); + } + + XMLFileSourcePrivateData (const std::string &path) + : m_stream (path) + { + mp_io.reset (new StreamIODevice (m_stream)); + } + + virtual void fetchData () + { + QXmlInputSource::fetchData (); + + // This feature is actually missing in the original implementation: throw an exception on error + if (mp_io->has_error ()) { + throw tl::Exception (tl::to_string (mp_io->errorString ())); + } + } + +private: + std::auto_ptr mp_io; + tl::InputStream m_stream; +}; + +XMLFileSource::XMLFileSource (const std::string &path, const std::string &progress_message) +{ + set_source (new XMLFileSourcePrivateData (path, progress_message)); +} + +XMLFileSource::XMLFileSource (const std::string &path) +{ + set_source (new XMLFileSourcePrivateData (path)); +} + +XMLFileSource::~XMLFileSource () +{ + // .. nothing yet .. +} + +// -------------------------------------------------------------------- +// XMLStreamSource implementation + +class XMLStreamSourcePrivateData + : public XMLSourcePrivateData +{ +public: + XMLStreamSourcePrivateData (StreamIODevice *io) + : mp_io (io) { // .. nothing yet .. } @@ -148,90 +652,69 @@ public: QXmlInputSource::fetchData (); // This feature is actually missing in the original implementation: throw an exception on error - if (mp_dev->has_error ()) { - throw tl::Exception (tl::to_string (mp_dev->errorString ())); + if (mp_io->has_error ()) { + throw tl::Exception (tl::to_string (mp_io->errorString ())); } } private: - StreamIODevice *mp_dev; + std::auto_ptr mp_io; }; -// -------------------------------------------------------------------- -// XMLFileSource implementation - -XMLFileSource::XMLFileSource (const std::string &path, const std::string &progress_message) - : mp_source (0), mp_io (0), m_stream (path) -{ - StreamIODevice *io = new StreamIODevice (m_stream, progress_message); - mp_io = io; - mp_source = new ErrorAwareQXmlInputSource (io); -} - -XMLFileSource::XMLFileSource (const std::string &path) - : mp_source (0), mp_io (0), m_stream (path) -{ - StreamIODevice *io = new StreamIODevice (m_stream); - mp_io = io; - mp_source = new ErrorAwareQXmlInputSource (io); -} - -XMLFileSource::~XMLFileSource () -{ - delete mp_source; - mp_source = 0; - delete mp_io; - mp_io = 0; -} - -// -------------------------------------------------------------------- -// XMLStreamSource implementation - XMLStreamSource::XMLStreamSource (tl::InputStream &s, const std::string &progress_message) { - StreamIODevice *io = new StreamIODevice (s, progress_message); - mp_io = io; - mp_source = new ErrorAwareQXmlInputSource (io); + set_source (new XMLStreamSourcePrivateData (new StreamIODevice (s, progress_message))); } XMLStreamSource::XMLStreamSource (tl::InputStream &s) { - StreamIODevice *io = new StreamIODevice (s); - mp_io = io; - mp_source = new ErrorAwareQXmlInputSource (io); + set_source (new XMLStreamSourcePrivateData (new StreamIODevice (s))); } XMLStreamSource::~XMLStreamSource () { - delete mp_source; - mp_source = 0; - delete mp_io; - mp_io = 0; + // .. nothing yet .. } // -------------------------------------------------------------------- // XMLParser implementation -XMLParser::XMLParser () +class XMLParserPrivateData + : public QXmlSimpleReader { - mp_reader = new QXmlSimpleReader (); +public: + XMLParserPrivateData () : QXmlSimpleReader () { } +}; + +XMLParser::XMLParser () + : mp_data (new XMLParserPrivateData ()) +{ + // .. nothing yet .. } XMLParser::~XMLParser () { - delete mp_reader; - mp_reader = 0; + delete mp_data; + mp_data = 0; } void -XMLParser::parse (XMLSource &source, QXmlDefaultHandler &handler) +XMLParser::parse (XMLSource &source, XMLStructureHandler &struct_handler) { - mp_reader->setContentHandler (&handler); - mp_reader->setErrorHandler (&handler); + SAXHandler handler (&struct_handler); - mp_reader->parse (source.source (), false /*=not incremental*/); + mp_data->setContentHandler (&handler); + mp_data->setErrorHandler (&handler); + + mp_data->parse (source.source (), false /*=not incremental*/); } +} + +#endif + +namespace tl { + // ----------------------------------------------------------------- // The C++ structure definition interface (for use cases see tlXMLParser.ut) @@ -294,128 +777,66 @@ XMLElementBase::write_string (tl::OutputStream &os, const std::string &s) } } -// XMLStructureHandler implementation +// -------------------------------------------------------------------------------------------------------- +// trureHandler implementation -XMLStructureHandler::XMLStructureHandler (const XMLElementBase *root, XMLReaderState *reader_state) - : QXmlDefaultHandler (), mp_root (root), mp_locator (0), mp_state (reader_state) +XMLStructureHandler::XMLStructureHandler (const XMLElementBase *root, XMLReaderState *reader_state) + : mp_root (root), mp_state (reader_state) { // .. nothing yet .. } void -XMLStructureHandler::setDocumentLocator (QXmlLocator *locator) -{ - mp_locator = locator; -} - -bool -XMLStructureHandler::startElement (const QString &qs_uri, const QString &qs_lname, const QString &qs_qname, const QXmlAttributes & /*atts*/) +XMLStructureHandler::start_element (const std::string &uri, const std::string &lname, const std::string &qname) { const XMLElementBase *new_element = 0; const XMLElementBase *parent = 0; - std::string uri (tl::to_string (qs_uri)); - std::string lname (tl::to_string (qs_lname)); - std::string qname (tl::to_string (qs_qname)); - - try { - - if (m_stack.size () == 0) { - if (! mp_root->check_name (uri, lname, qname)) { - throw tl::XMLException (tl::to_string (QObject::tr ("Root element must be ")) + mp_root->name ()); - } - new_element = mp_root; - } else { - parent = m_stack.back (); - if (parent) { - for (XMLElementBase::iterator c = parent->begin (); c != parent->end (); ++c) { - if ((*c)->check_name (uri, lname, qname)) { - new_element = (*c).get (); - break; - } + if (m_stack.size () == 0) { + if (! mp_root->check_name (uri, lname, qname)) { + throw tl::XMLException (tl::to_string (tr ("Root element must be ")) + mp_root->name ()); + } + new_element = mp_root; + } else { + parent = m_stack.back (); + if (parent) { + for (XMLElementBase::iterator c = parent->begin (); c != parent->end (); ++c) { + if ((*c)->check_name (uri, lname, qname)) { + new_element = (*c).get (); + break; } } } - - if (new_element) { - new_element->create (parent, *mp_state, uri, lname, qname); - } - - } catch (tl::XMLException &ex) { - throw tl::XMLLocatedException (ex.raw_msg (), mp_locator->lineNumber (), mp_locator->columnNumber ()); - } catch (tl::Exception &ex) { - throw tl::XMLLocatedException (ex.msg (), mp_locator->lineNumber (), mp_locator->columnNumber ()); } - m_stack.push_back (new_element); - // successful - return true; + if (new_element) { + new_element->create (parent, *mp_state, uri, lname, qname); + } + + m_stack.push_back (new_element); } -bool -XMLStructureHandler::endElement (const QString &qs_uri, const QString &qs_lname, const QString &qs_qname) +void +XMLStructureHandler::end_element (const std::string &uri, const std::string &lname, const std::string &qname) { const XMLElementBase *element = m_stack.back (); m_stack.pop_back (); - std::string uri (tl::to_string (qs_uri)); - std::string lname (tl::to_string (qs_lname)); - std::string qname (tl::to_string (qs_qname)); - - try { - if (! element) { - // inside unknown element - } else if (m_stack.size () == 0) { - element->finish (0, *mp_state, uri, lname, qname); - } else { - element->finish (m_stack.back (), *mp_state, uri, lname, qname); - } - } catch (tl::XMLException &ex) { - throw tl::XMLLocatedException (ex.raw_msg (), mp_locator->lineNumber (), mp_locator->columnNumber ()); - } catch (tl::Exception &ex) { - throw tl::XMLLocatedException (ex.msg (), mp_locator->lineNumber (), mp_locator->columnNumber ()); + if (! element) { + // inside unknown element + } else if (m_stack.size () == 0) { + element->finish (0, *mp_state, uri, lname, qname); + } else { + element->finish (m_stack.back (), *mp_state, uri, lname, qname); } - - // successful - return true; } -bool -XMLStructureHandler::characters (const QString &t) +void +XMLStructureHandler::characters (const std::string &t) { - try { - if (m_stack.back ()) { - m_stack.back ()->cdata (tl::to_string (t), *mp_state); - } - } catch (tl::XMLException &ex) { - throw tl::XMLLocatedException (ex.raw_msg (), mp_locator->lineNumber (), mp_locator->columnNumber ()); - } catch (tl::Exception &ex) { - throw tl::XMLLocatedException (ex.msg (), mp_locator->lineNumber (), mp_locator->columnNumber ()); + if (m_stack.back ()) { + m_stack.back ()->cdata (t, *mp_state); } - - // successful - return true; -} - -bool -XMLStructureHandler::error (const QXmlParseException &ex) -{ - throw tl::XMLLocatedException (tl::to_string (ex.message ()), ex.lineNumber (), ex.columnNumber ()); -} - -bool -XMLStructureHandler::fatalError (const QXmlParseException &ex) -{ - throw tl::XMLLocatedException (tl::to_string (ex.message ()), ex.lineNumber (), ex.columnNumber ()); -} - -bool -XMLStructureHandler::warning (const QXmlParseException &ex) -{ - tl::XMLLocatedException lex (tl::to_string (ex.message ()), ex.lineNumber (), ex.columnNumber ()); - tl::warn << lex.msg (); - // continue - return true; } // -------------------------------------------------------------------- diff --git a/src/tl/tl/tlXMLParser.h b/src/tl/tl/tlXMLParser.h index 2db932a1d..c8c9d7359 100644 --- a/src/tl/tl/tlXMLParser.h +++ b/src/tl/tl/tlXMLParser.h @@ -26,14 +26,6 @@ #include "tlCommon.h" -#if !defined(HAVE_XML) -# error tl::XMLParser not available without QtXml -#endif - -#include -#include -#include - #include #include @@ -55,7 +47,7 @@ class TL_PUBLIC XMLException : public tl::Exception { public: XMLException (const char *msg) - : Exception (tl::to_string (QObject::tr ("XML parser error: %s")).c_str ()), + : Exception (tl::to_string (tr ("XML parser error: %s")).c_str ()), m_msg (msg) { // .. nothing yet .. @@ -91,9 +83,9 @@ private: static std::string fmt (int line, int /*column*/) { if (line < 0) { - return tl::to_string (QObject::tr ("XML parser error: %s")).c_str (); + return tl::to_string (tr ("XML parser error: %s")).c_str (); } else { - return tl::to_string (QObject::tr ("XML parser error: %s in line %d, column %d")).c_str (); + return tl::to_string (tr ("XML parser error: %s in line %d, column %d")).c_str (); } } }; @@ -305,6 +297,9 @@ private: std::vector m_objects; }; +// The opaque source type +class XMLSourcePrivateData; + /** * @brief A generic XML text source class * @@ -316,17 +311,22 @@ private: class TL_PUBLIC XMLSource { public: - XMLSource () + XMLSource (); + virtual ~XMLSource (); + + virtual XMLSourcePrivateData *source () { - // .. nothing yet .. - } - - virtual ~XMLSource () - { - // .. nothing yet .. + return mp_source; } - virtual QXmlInputSource *source () = 0; +protected: + void set_source (XMLSourcePrivateData *source) + { + mp_source = source; + } + +private: + XMLSourcePrivateData *mp_source; }; /** @@ -338,14 +338,6 @@ class TL_PUBLIC XMLStringSource : public XMLSource public: XMLStringSource (const std::string &string); virtual ~XMLStringSource (); - - virtual QXmlInputSource *source () - { - return mp_source; - } - -private: - QXmlInputSource *mp_source; }; /** @@ -358,16 +350,6 @@ public: XMLFileSource (const std::string &path); XMLFileSource (const std::string &path, const std::string &progress_message); virtual ~XMLFileSource (); - - virtual QXmlInputSource *source () - { - return mp_source; - } - -private: - QXmlInputSource *mp_source; - QIODevice *mp_io; - tl::InputStream m_stream; }; /** @@ -382,37 +364,9 @@ public: XMLStreamSource (tl::InputStream &stream); XMLStreamSource (tl::InputStream &stream, const std::string &progress_message); virtual ~XMLStreamSource (); - - virtual QXmlInputSource *source () - { - return mp_source; - } - -private: - QXmlInputSource *mp_source; - QIODevice *mp_io; }; -/** - * @brief The XML parser class - * - * The class is the basic wrapper around the Qt XML parser. - * It is provided mainly for compatibility with the "libparsifal branch". - */ - -class TL_PUBLIC XMLParser -{ -public: - XMLParser (); - ~XMLParser (); - - void parse (XMLSource &source, QXmlDefaultHandler &handler); - -private: - QXmlSimpleReader *mp_reader; -}; - // ----------------------------------------------------------------- // The C++ structure definition interface (for use cases see tlXMLParser.ut) @@ -433,28 +387,40 @@ struct pass_by_ref_tag { * elements to implement the search algorithm. */ -class TL_PUBLIC XMLStructureHandler - : public QXmlDefaultHandler +class TL_PUBLIC XMLStructureHandler { public: XMLStructureHandler (const XMLElementBase *root, XMLReaderState *reader_state); - bool characters (const QString &ch); - bool endElement (const QString &namespaceURI, const QString &localName, const QString &qName); - bool startElement (const QString &namespaceURI, const QString &localName, const QString &qName, const QXmlAttributes &atts); - bool error (const QXmlParseException &exception); - bool fatalError (const QXmlParseException &exception); - bool warning (const QXmlParseException &exception); - - void setDocumentLocator (QXmlLocator *locator); + void characters (const std::string &ch); + void end_element (const std::string &uri, const std::string &lname, const std::string &qname); + void start_element (const std::string &uri, const std::string &lname, const std::string &qname); private: - std::vector m_stack; + std::vector m_stack; const XMLElementBase *mp_root; - QXmlLocator *mp_locator; XMLReaderState *mp_state; }; +class XMLParserPrivateData; + +/** + * @brief The XML parser class + * This is the main entry point. It will take a structure handler and + * parse the given source. + */ +class TL_PUBLIC XMLParser +{ +public: + XMLParser (); + ~XMLParser (); + + void parse (XMLSource &source, XMLStructureHandler &handler); + +private: + XMLParserPrivateData *mp_data; +}; + /** * @brief XMLElementProxy element of the XML structure definition *